]> andersk Git - libfaim.git/blob - utils/aimdump/main.c
Added aimdump.
[libfaim.git] / utils / aimdump / main.c
1 /*
2  *
3  *
4  *
5  *
6  */
7
8 #include "aimdump.h"
9
10 #define IMAGEFILE "ibmboot.img"
11 #define DEVNAME "eth0"
12
13 pcap_t *pd = NULL;
14
15 static u_int8_t clientaddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0x0ff, 0xff}; /* loaded with client address */
16 static u_int8_t multicastaddr[ETH_ALEN] = {0x03, 0x00, 0x02, 0x00, 0x00, 0x00};
17
18 pcap_t *open_pcap(char *device)
19 {
20   pcap_t *pd = NULL;
21   char errbuf[PCAP_ERRBUF_SIZE];
22
23   if (device == NULL)
24     {
25       if ( (device = pcap_lookupdev(errbuf)) == NULL)
26         {
27           fprintf(stderr, "pcap_lookup: %s\n", errbuf);
28           return NULL;
29         }
30     }
31   
32   if ( (pd = pcap_open_live(device, 1500, 1, 500, errbuf)) == NULL)
33     {
34       fprintf(stderr, "pcap_open_live: %s\n", errbuf);
35       return NULL;
36     }
37   
38   return pd;
39 }
40
41 void showstats(pcap_t *pd)
42 {
43   struct pcap_stat stats;
44   
45   fflush(stdout);
46   printf("\n");
47   
48   if (pcap_stats(pd, &stats) < 0)
49     {
50       fprintf(stderr, "cap_stats: %s\n", pcap_geterr(pd));
51       return;
52     }
53   printf("%d packets recieved by filter\n", stats.ps_recv);
54   printf("%d packets dropped by kernel\n", stats.ps_drop);
55
56   return;
57 }
58
59 char *next_pcap(pcap_t *pd, struct pcap_pkthdr *hdr)
60 {
61   char *ptr;
62   
63   while ( (ptr = (char *)pcap_next(pd, hdr)) == NULL)
64     ;
65
66   return ptr;
67 }
68
69 /*
70  * This covers stage two of the fast-path, after we've determined its 
71  * an incoming RPL frame.  
72  *
73  */
74 void processframe(struct pcap_pkthdr *hdr, char *pkt, char *device)
75 {
76   static struct ether_header *ether = NULL;
77 #if 0
78   u_int8_t cmpaddr[ETH_ALEN] = {0x10, 0x00, 0x5a, 0x3b, 0x0b, 0x72};
79   u_int8_t cmpaddr[ETH_ALEN] = {0x03, 0x00, 0x02, 0x00, 0x00, 0x00};
80 #endif
81   if ( (!hdr) || (!pkt) )
82     return;
83
84   ether = (struct ether_header *)pkt;
85   
86   if (hdr->caplen != hdr->len)
87     fprintf(stderr, "rpld: caplen/len mismatch\n");
88
89
90   if ((clientaddr[0] != 0xff) && cmpether(clientaddr, ether->ether_shost))
91     {
92       int command = 0x0000;
93       fprintf(stderr, "rpld: got a %sframe from our client\n", (cmpether(multicastaddr, ether->ether_dhost))?"multicast ":"");
94       command = (pkt[19]<<8)+pkt[20];
95       fprintf(stderr, "rpld: command: 0x%04x\n", command);
96       
97 #if 0
98       if (command == 0x0001) /* FIND */
99         send_found(link, device);
100       else if (command == 0x0010) /* Send File Request */
101         send_file(link, device);
102 #endif
103       
104     }
105   else if (cmpether(multicastaddr, ether->ether_dhost))
106     {
107       if (clientaddr[0] != 0xff)
108         {
109           /* we're already servicing another client */
110           fprintf(stderr, "rpld: not adding client %s\n", printether(ether->ether_shost));
111           return;
112         }
113       else
114         {
115           /* we're not busy yet, lets process this one */
116           fprintf(stderr, "rpld: adding client %s\n", printether(ether->ether_shost));
117           memcpy(clientaddr, ether->ether_shost, ETH_ALEN);
118         }
119     }
120 #if 0
121   else if (cmpether(clientaddr, ether->ether_dhost))
122     {
123       fprintf(stderr, "rpld: showing outgoing frame...\n");
124       printframe(hdr, pkt);
125     }
126 #endif
127   else
128     fprintf(stderr, "rpld: uncaught case\n");
129
130 #if 0
131   if (cmpether(cmpaddr, ether->ether_shost) ||
132       cmpether(cmpaddr, ether->ether_dhost) )
133     {
134       printf("\n\n%s > ", printether(ether->ether_shost));
135       printf("%s\n", printether(ether->ether_dhost));
136
137       if (pkt[20] != 0x01)
138         printf("\aSTATUS CHANGE\n");
139
140       //pkt = 18; /* skip over ethernet headers */
141       for (i=0;i<hdr->caplen;i+=2)
142         {
143           if (!((i)%8))
144             printf("\n\t");
145           printf("%02x%02x ", pkt[i] &0xff, pkt[i+1] & 0xff);
146         }
147     }
148   else 
149     return;
150 #endif
151 }
152
153 void sigint(int sig)
154 {
155   fflush(stdout);
156   showstats(pd);
157   exit(0);
158   return;
159 }
160
161 struct flaphdr {
162   __u8 start;
163   __u8 channel;
164   __u16 seqnum;
165   __u16 len;
166 };
167
168 struct snachdr {
169   u_short family;
170   u_short subtype;
171   u_char flags[2];
172   u_long id;
173 };
174
175 struct subtype_s {
176   char *name;
177   void (*parser)(u_char *data, int len);
178 };
179
180 struct snactype_s {
181   char *family;
182   struct subtype_s subtypes[21];
183 } snactypes[16] = {
184   {"Invalid", {
185     {NULL, NULL}}
186   },
187   {"General", {
188     {"Invalid", NULL},
189     {"Error", NULL},
190     {"Client Ready", NULL},
191     {"Server Ready", NULL}, 
192     {"Service Request", NULL},
193     {"Redirect", NULL},
194     {"Rate Information Request", NULL},
195     {"Rate Information", NULL},
196     {"Rate Information Ack", NULL},
197     {"Rate Information Change", NULL},
198     {"Server Pause", NULL},
199     {"Server Resume", NULL},
200     {"Request Personal User Information", NULL},
201     {"Personal User Information", NULL},
202     {"Evil Notification", NULL},
203     {"Migration notice", NULL},
204     {"Message of the Day", NULL},
205     {"Set Privacy Flags", NULL},
206     {"Well Known URL", NULL},
207     {"NOP", NULL},
208     {NULL, NULL}}
209   },
210   {"Location", {
211     {"Invalid", NULL},
212     {"Error", NULL},
213     {"Request Rights", NULL},
214     {"Rights Information", NULL}, 
215     {"Set user information", NULL}, 
216     {"Request User Information", NULL}, 
217     {"User Information", NULL}, 
218     {"Watcher Sub Request", NULL},
219     {"Watcher Notification", NULL},
220     {NULL, NULL}}
221   },
222   {"Buddy List Management", {
223     {"Invalid", NULL}, 
224     {"Error", NULL}, 
225     {"Request Rights", NULL},
226     {"Rights Information", NULL},
227     {"Add Buddy", NULL}, 
228     {"Remove Buddy", NULL}, 
229     {"Watcher List Query", NULL}, 
230     {"Watcher List Response", NULL}, 
231     {"Watcher SubRequest", NULL}, 
232     {"Watcher Notification", NULL}, 
233     {"Reject Notification", NULL}, 
234     {"Oncoming Buddy", NULL}, 
235     {"Offgoing Buddy", NULL},
236     {NULL, NULL}},
237   },
238   {"Messeging", {
239     {"Invalid", NULL},
240     {"Error", NULL}, 
241     {"Add ICBM Parameter", NULL},
242     {"Remove ICBM Parameter", NULL}, 
243     {"Request Parameter Information", NULL},
244     {"Parameter Information", NULL},
245     {"Outgoing Message", NULL}, 
246     {"Incoming Message", parser_icbm_incoming},
247     {"Evil Request", NULL},
248     {"Evil Reply", NULL}, 
249     {"Missed Calls", NULL},
250     {"Message Error", NULL}, 
251     {"Host Ack", NULL},
252     {NULL, NULL}}
253   },
254   {"Advertisements", {
255     {"Invalid", NULL}, 
256     {"Error", NULL}, 
257     {"Request Ad", NULL},
258     {"Ad Data (GIFs)", NULL},
259     {NULL, NULL}}
260   },
261   {"Invitation / Client-to-Client", {
262     {"Invalid", NULL},
263     {"Error", NULL},
264     {"Invite a Friend", NULL},
265     {"Invitation Ack", NULL},
266     {NULL, NULL}}
267   },
268   {"Administrative", {
269     {"Invalid", NULL},
270     {"Error", NULL},
271     {"Information Request", NULL},
272     {"Information Reply", NULL},
273     {"Information Change Request", NULL},
274     {"Information Chat Reply", NULL},
275     {"Account Confirm Request", NULL},
276     {"Account Confirm Reply", NULL},
277     {"Account Delete Request", NULL},
278     {"Account Delete Reply", NULL},
279     {NULL, NULL}}
280   },
281   {"Popups", {
282     {"Invalid", NULL},
283     {"Error", NULL},
284     {"Display Popup", NULL},
285     {NULL, NULL}}
286   },
287   {"BOS", {
288     {"Invalid", NULL},
289     {"Error", NULL},
290     {"Request Rights", NULL},
291     {"Rights Response", NULL},
292     {"Set group permission mask", NULL},
293     {"Add permission list entries", NULL},
294     {"Delete permission list entries", NULL},
295     {"Add deny list entries", NULL},
296     {"Delete deny list entries", NULL},
297     {"Server Error", NULL},
298     {NULL, NULL}}
299   },
300   {"User Lookup", {
301     {"Invalid", NULL},
302     {"Error", NULL},
303     {"Search Request", NULL},
304     {"Search Response", NULL},
305     {NULL, NULL}}
306   },
307   {"Stats", {
308     {"Invalid", NULL},
309     {"Error", NULL},
310     {"Set minimum report interval", NULL},
311     {"Report Events", NULL},
312     {NULL, NULL}}
313   },
314   {"Translate", {
315     {"Invalid", NULL},
316     {"Error", NULL},
317     {"Translate Request", NULL},
318     {"Translate Reply", NULL},
319     {NULL, NULL}}
320   },
321   {"Chat Navigation", {
322     {"Invalid", NULL},
323     {"Error", NULL},
324     {"Request rights", NULL},
325     {"Request Exchange Information", NULL},
326     {"Request Room Information", NULL},
327     {"Request Occupant List", NULL},
328     {"Search for Room", NULL},
329     {"Create Room", NULL},
330     {"Navigation Information", NULL},
331     {NULL, NULL}}
332   },
333   {"Chat", {
334     {"Invalid", NULL},
335     {"Error", NULL},
336     {"Room Information Update", NULL},
337     {"Users Joined", NULL},
338     {"Users Left", NULL},
339     {"Outgoing Message", NULL},
340     {"Incoming Message", NULL},
341     {"Evil Request", NULL},
342     {"Evil Reply", NULL},
343     {"Chat Error", NULL},
344     {NULL, NULL}}
345   },
346   {NULL, {
347     {NULL, NULL}}
348   }
349 };
350
351 void detectaim(struct pcap_pkthdr *hdr, char *pkt)
352 {
353   int i;
354   struct ether_header *ether = NULL;
355   struct iphdr *ip = NULL;
356   struct tcphdr*tcp= NULL;
357   struct flaphdr *flap = NULL;
358   struct snachdr *snac = NULL;
359   char *orig = pkt;
360   u_int newlen;
361   int maxfamily = 0;
362   int maxsubtype = 0;
363     
364   if ( (!hdr) || (!pkt) )
365     return;
366
367   if (hdr->caplen != hdr->len)
368     fprintf(stderr, "aimdump: caplen/len mismatch\n");
369
370   newlen = hdr->caplen;
371
372   ether = (struct ether_header *)pkt;
373   
374 #if 0
375   printf("\n\naimdump: %s > ", printether(ether->ether_shost));
376   printf("%s\n", printether(ether->ether_dhost));
377 #endif
378
379   pkt += sizeof(struct ether_header); /* skip over ether headers */
380   newlen -= sizeof(struct ether_header);
381
382   ip = (struct iphdr *)pkt;
383   if (ip->version != 0x4)
384     return; /* ditch non IPv4 packets */
385   pkt += (ip->ihl)*4;
386   newlen -= (ip->ihl)*4;
387
388   tcp = (struct tcphdr *)pkt;
389   if(!tcp->psh) /* we only want actual data packets */
390     return;
391   pkt += sizeof(struct tcphdr);
392   newlen -= sizeof(struct tcphdr);
393
394   flap = (struct flaphdr *)pkt;
395
396   if (flap->start != 0x2a)
397     return; /* ditch non-FLAP packets */
398
399 #if 0
400   /* TODO: notify user of new connections (SYN) and closed connections (FIN) */
401   printf("\nTCP options: %s %s %s %s %s %s\n\n",
402          tcp->fin?"fin":"",
403          tcp->syn?"syn":"",
404          tcp->rst?"rst":"",
405          tcp->psh?"psh":"",
406          tcp->ack?"ack":"",
407          tcp->urg?"urg":"");
408 #endif
409
410   flap->seqnum = ntohs(flap->seqnum);
411   flap->len = ntohs(flap->len);
412
413   snac = (struct snachdr *)(pkt+6);
414
415   snac->family = ntohs(snac->family);
416   snac->subtype= ntohs(snac->subtype);
417   snac->id = (htons(snac->id & 0x0000ffff)) + (htons(snac->id >>16)<<16);
418   
419   printf("\n--------------------\n");
420   printf("FLAP:\n");
421   printf("\tChannel:\t0x%02x\t\tSeqNum:\t0x%04x\n\tLength:\t\t0x%04x\n",
422          flap->channel,
423          flap->seqnum,
424          flap->len);
425   printf("SNAC:\n");
426
427
428   /* for overrun checking... */
429   for (maxfamily=1;snactypes[maxfamily].family; maxfamily++)
430     ;
431   if (snac->family <= maxfamily)
432     {
433       for (maxsubtype=1;snactypes[snac->family].subtypes[maxsubtype].name; maxsubtype++)
434         ;
435     }
436   maxfamily--;
437   maxsubtype--;
438
439   printf("\tFamily:\t\t0x%04x (%s)\n", 
440          snac->family,
441          (snac->family > maxfamily)?"Out of Range":snactypes[snac->family].family);
442   printf("\tSubtype:\t0x%04x (%s)\n",
443          snac->subtype,
444          (snac->subtype > maxsubtype)?"Out of Range":snactypes[snac->family].subtypes[snac->subtype].name);
445   printf("\tFlags:\t\t0x%02x,0x%02x\tID:\t0x%08lx\n", snac->flags[0], snac->flags[1], snac->id);
446
447   /* jump around flap+snac */
448   pkt += 16;
449   newlen -= 16;
450
451   if (snactypes[snac->family].subtypes[snac->subtype].parser)
452     (*(snactypes[snac->family].subtypes[snac->subtype].parser))((u_char *)pkt, newlen);
453
454   printf("\nRAW:\n");
455
456   for (i=0;i<newlen;i+=2)
457     {
458       if (!((i)%16))
459         printf("\n\t");
460       printf("%02x%02x ", pkt[i] &0xff, pkt[i+1] & 0xff);
461     }
462   printf("\n\n");
463
464   fflush(stdout);
465   pkt = orig;
466 }
467
468 int main(int argc, char **argv)
469 {
470   struct pcap_pkthdr hdr;
471   char *pkt;
472
473   if ((pd = open_pcap(NULL)) == NULL)
474     {
475       fprintf(stderr, "error in open_pcap\n");
476       exit (-1);
477     }
478
479   signal(SIGINT, sigint);
480
481 #if 0  
482   if ((localmac = (u_int8_t *)get_hwaddr(link, DEVNAME, errbuf)) == NULL)
483     {
484       fprintf(stderr, "rpld: Unable to get local MAC address, using default\n");
485       localmac = defsource;
486     }
487
488   fprintf(stderr, "rpld: Local MAC Address: %s\n", printether((u_int8_t *)localmac));
489 #endif
490
491 #if 1
492   while ((pkt = next_pcap(pd, &hdr)))
493     {
494       detectaim(&hdr, pkt);
495       //printframe(&hdr, pkt);
496     }
497 #endif
498 #if 0
499   while (pkt = next_pcap(pd, &hdr))
500     {
501       /*
502        * Since this is the fast-path (it gets executed for 
503        * EVERY frame that gets captured -- this could be HUGE
504        * on busy 100mb LANs), we need to determine if this frame
505        * needs further processing as fast as possible... 
506        */
507       etherhdr = (struct ether_header *)pkt;
508      
509       /* this should cover everything */
510       if ( (etherhdr->ether_type == (ETHERTYPE_INCOMING<<8)) ||
511            (etherhdr->ether_type == (ETHERTYPE_FOUND<<8)) ||
512            (etherhdr->ether_type == (ETHERTYPE_DATA<<8)) )
513         processframe(&hdr, pkt, link, DEVNAME);
514       else 
515         fprintf(stderr, "rpld: skipping ethertype %04x\n", etherhdr->ether_type);
516     }
517 #endif
518   showstats(pd);
519
520   return 0;
521 }
This page took 0.295483 seconds and 5 git commands to generate.