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