/[LeafOK_CVS]/pvpgn-1.7.4/src/bnpcap/bnpcap.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bnpcap/bnpcap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (hide annotations) (vendor branch)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch: GNU, MAIN
CVS Tags: arelease, HEAD
Changes since 1.1: +0 -0 lines
Content type: text/x-csrc
no message

1 sysadm 1.1 /*
2     * Copyright (C) 2001 Marco Ziech (mmz@gmx.net)
3     *
4     * This program is free software; you can redistribute it and/or
5     * modify it under the terms of the GNU General Public License
6     * as published by the Free Software Foundation; either version 2
7     * of the License, or (at your option) any later version.
8     *
9     * This program is distributed in the hope that it will be useful,
10     * but WITHOUT ANY WARRANTY; without even the implied warranty of
11     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12     * GNU General Public License for more details.
13     *
14     * You should have received a copy of the GNU General Public License
15     * along with this program; if not, write to the Free Software
16     * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17     */
18     #include "common/setup_before.h"
19     #include <stdio.h>
20     #include <pcap.h>
21     #include <errno.h>
22     #include <netinet/in.h>
23     #include <string.h>
24     #include "compat/strerror.h"
25     #include "compat/getopt.h"
26     #include "common/init_protocol.h"
27     #include "common/bnet_protocol.h"
28     #include "common/udp_protocol.h"
29     #include "common/packet.h"
30     #include "common/eventlog.h"
31     #include "common/hexdump.h"
32     #include "common/list.h"
33     #include "common/version.h"
34     #include "common/util.h"
35     #include "common/setup_after.h"
36    
37     /* FIXME: everywhere: add checks for NULL pointers */
38    
39     char *filename = NULL;
40     pcap_t *pc;
41     char ebuf[PCAP_ERRBUF_SIZE];
42    
43    
44     int bnpcap_dodebug = 0;
45     int bnpcap_beverbose = 0;
46    
47     unsigned int listen_port = 6112;
48    
49     /********************* CONNECTIONS ********************/
50    
51     typedef enum {
52     tcp_state_none,
53     tcp_state_syn,
54     tcp_state_ack,
55     tcp_state_ok
56     } t_tcp_state;
57    
58     typedef struct {
59     /* It's IPV4 */
60     unsigned int ip;
61     unsigned short port;
62     } t_bnpcap_addr;
63    
64     /* To track connections ... */
65     typedef struct {
66     t_bnpcap_addr client;
67     t_bnpcap_addr server;
68     t_packet_class class;
69     t_tcp_state tcpstate;
70     int incomplete;
71     int clientoff;
72     t_packet *clientpkt;
73     int serveroff;
74     t_packet *serverpkt;
75     t_list * packets;
76     } t_bnpcap_conn;
77    
78     typedef struct {
79     t_packet_dir dir;
80     struct timeval tv;
81     unsigned int id;
82     t_packet *p;
83     } t_bnpcap_packet;
84    
85     t_list * conns;
86     t_list * udppackets;
87    
88     struct timeval packettime;
89    
90     static unsigned int current_packet_id = 1;
91    
92     /*********************** HEADERS **********************/
93    
94     /* FIXME: don't assume that's always true */
95     typedef unsigned char u8;
96     typedef unsigned short u16;
97     typedef unsigned int u32;
98    
99     /************************** TCP ***********************/
100    
101     typedef struct {
102     u16 sport;
103     u16 dport;
104     u32 seqno;
105     u32 ackno;
106     u16 stuff; /* Data offset, various flags */
107     u16 window;
108     u16 checksum;
109     u16 urgp; /* Urgent Pointer (if URG flag set) */
110     /* options */
111     } t_tcp_header_raw;
112    
113     typedef struct {
114     unsigned short sport;
115     unsigned short dport;
116     unsigned int seqno;
117     unsigned int ackno;
118     unsigned char doffset;
119     unsigned short flags;
120     #define TCP_URG 0x20 /* Urgent pointer field significant */
121     #define TCP_ACK 0x10 /* Acknowlegdement field significant */
122     #define TCP_PSH 0x08 /* Push function */
123     #define TCP_RST 0x04 /* Reset connection */
124     #define TCP_SYN 0x02 /* Synchronize sequence numbers */
125     #define TCP_FIN 0x01 /* No more data from sender (finish) */
126     unsigned short window;
127     unsigned short checksum;
128     unsigned short urgp;
129     /* options */
130     } t_tcp_header;
131    
132     /******************************** UDP ************************/
133    
134     typedef struct {
135     u16 sport;
136     u16 dport;
137     u16 len;
138     u16 checksum;
139     } t_ip_udp_header_raw;
140    
141     typedef struct {
142     unsigned short sport;
143     unsigned short dport;
144     unsigned short len;
145     unsigned short checksum;
146     } t_ip_udp_header;
147    
148     /******************************** IP *************************/
149    
150     typedef struct {
151     u8 versionihl;
152     u8 tos;
153     u16 len;
154     u16 id;
155     u16 flagsoffset;
156     u8 ttl;
157     u8 protocol;
158     u16 checksum;
159     u32 src;
160     u32 dst;
161     /* options */
162     } t_ip_header_raw;
163    
164     typedef struct {
165     unsigned char version;
166     unsigned char ihl;
167     unsigned char tos;
168     unsigned short len;
169     unsigned short id;
170     unsigned char flags;
171     #define IP_DF 0x02 /* 1 == Don't fragment */
172     #define IP_MF 0x01 /* 1 == More fragments */
173     unsigned short offset;
174     unsigned char ttl;
175     unsigned char protocol;
176     unsigned short checksum;
177     unsigned int src;
178     unsigned int dst;
179     /* options */
180     } t_ip_header;
181    
182     /******************************* ETHERNET *****************************/
183    
184     typedef struct {
185     u8 dst[6]; /* Ethernet hardware address */
186     u8 src[6]; /* Ethernet hardware address */
187     u16 type; /* Ethernet_II: protocol type */
188     /* FIXME: Ethernet [802.2|802.3|SNAP]: maybe something else (eg. length) */
189     } t_ether_raw;
190    
191     /************************************************************************/
192     /************************* CONNECTION FUNCTIONS *************************/
193    
194     static t_bnpcap_conn * bnpcap_conn_new(t_bnpcap_addr const *s, t_bnpcap_addr const *d)
195     {
196     t_bnpcap_conn * c;
197    
198     c = (t_bnpcap_conn *) malloc(sizeof(t_bnpcap_conn)); /* avoid warning */
199     if (!c) {
200     eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno));
201     return NULL;
202     }
203     if (d->port==listen_port || d->port==6200) { /* FIXME: That's dirty: We assume the server is on port 6112 */
204     memcpy(&c->client,s,sizeof(t_bnpcap_addr));
205     memcpy(&c->server,d,sizeof(t_bnpcap_addr));
206     } else {
207     memcpy(&c->client,d,sizeof(t_bnpcap_addr));
208     memcpy(&c->server,s,sizeof(t_bnpcap_addr));
209     }
210     c->class = packet_class_init;
211     c->packets = list_create();
212     c->incomplete = 0;
213     c->tcpstate = tcp_state_none;
214     c->clientoff = 0;
215     c->clientpkt = NULL;
216     c->serveroff = 0;
217     c->serverpkt = NULL;
218     return c;
219     }
220    
221     static void bnpcap_conn_set_class(t_bnpcap_conn *c, t_packet_class class)
222     {
223     c->class = class;
224     }
225    
226     static t_packet_class bnpcap_conn_get_class(t_bnpcap_conn *c)
227     {
228     return c->class;
229     }
230    
231     static t_bnpcap_conn * bnpcap_conn_find(t_bnpcap_addr const *s, t_bnpcap_addr const *d)
232     {
233     t_elem * curr;
234    
235     LIST_TRAVERSE(conns,curr) {
236     t_bnpcap_conn *c;
237    
238     c = elem_get_data(curr);
239     if (((c->client.ip==s->ip)&&(c->client.port==s->port))&&
240     ((c->server.ip==d->ip)&&(c->server.port==d->port))) {
241     return c;
242     } else if (((c->client.ip==d->ip)&&(c->client.port==d->port))&&
243     ((c->server.ip==s->ip)&&(c->server.port==s->port))) {
244     return c;
245     }
246     }
247     return NULL;
248     }
249    
250     static t_packet_dir bnpcap_conn_get_dir(t_bnpcap_conn const * c, t_bnpcap_addr const *s, t_bnpcap_addr const *d)
251     {
252     if (((c->client.ip==s->ip)&&(c->client.port==s->port))&&
253     ((c->server.ip==d->ip)&&(c->server.port==d->port)))
254     return packet_dir_from_client;
255     else
256     return packet_dir_from_server;
257     }
258    
259     static int bnpcap_conn_add_packet(t_bnpcap_conn *c, t_bnpcap_packet *bp) {
260     eventlog(eventlog_level_debug,__FUNCTION__,"id=%u ",bp->id);
261     list_append_data(c->packets,bp);
262     packet_add_ref(bp->p);
263     return 0;
264     }
265    
266     static int bnpcap_conn_packet(unsigned int sip, unsigned short sport, unsigned int dip, unsigned short dport, unsigned char const * data, unsigned int len)
267     {
268     t_bnpcap_addr s;
269     t_bnpcap_addr d;
270     t_bnpcap_conn *c;
271     t_bnpcap_packet *bp;
272    
273     s.ip = sip;
274     s.port = sport;
275     d.ip = dip;
276     d.port = dport;
277    
278     if ((c = bnpcap_conn_find(&s,&d))) {
279     eventlog(eventlog_level_debug,__FUNCTION__,"adding packet to existing connection");
280     if (c->tcpstate==tcp_state_ack) {
281     c->tcpstate = tcp_state_ok;
282     } else if (c->tcpstate==tcp_state_syn) {
283     c->incomplete = 1; /* ACK missing */
284     c->tcpstate = tcp_state_ok;
285     }
286     } else {
287     eventlog(eventlog_level_debug,__FUNCTION__,"adding packet to incomplete connection");
288     c = bnpcap_conn_new(&s,&d);
289     bnpcap_conn_set_class(c,packet_class_raw); /* we don't know the init sequence */
290     c->incomplete = 1;
291     c->tcpstate = tcp_state_ok;
292     list_append_data(conns,c);
293     }
294     if (c->tcpstate!=tcp_state_ok) {
295     eventlog(eventlog_level_warn,__FUNCTION__,"connection got packet in wrong state!");
296     }
297     if (bnpcap_conn_get_class(c) == packet_class_init) {
298     if (len>1) {
299     eventlog(eventlog_level_warn,__FUNCTION__,"init packet larger than 1 byte");
300     }
301     switch (data[0]) {
302     case CLIENT_INITCONN_CLASS_BNET:
303     bnpcap_conn_set_class(c,packet_class_bnet);
304     break;
305     case CLIENT_INITCONN_CLASS_FILE:
306     bnpcap_conn_set_class(c,packet_class_file);
307     break;
308     case 0xf7: // W3 matchmaking hack
309     eventlog(eventlog_level_info,__FUNCTION__,"matchmaking packet");
310     bnpcap_conn_set_class(c,packet_class_bnet);
311     break;
312     default:
313     bnpcap_conn_set_class(c,packet_class_raw);
314     }
315     } else {
316     t_packet *p;
317     unsigned int off;
318     unsigned char const *datap = data;
319     int always_complete = 0;
320    
321    
322     if (bnpcap_conn_get_class(c) == packet_class_raw)
323     always_complete = 1; /* There is no size field */
324     if (bnpcap_conn_get_class(c) == packet_class_file)
325     always_complete = 1; /* Size field isn't always there */
326    
327     if (always_complete) {
328     /* packet is always complete */
329     eventlog(eventlog_level_debug,__FUNCTION__,"packet is always complete (class=%d)",bnpcap_conn_get_class(c));
330     bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */
331     if (!bp) {
332     eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno));
333     return -1;
334     }
335     bp->dir = bnpcap_conn_get_dir(c,&s,&d);
336     bp->p = packet_create(bnpcap_conn_get_class(c));
337     bp->id = current_packet_id++;
338     if (!bp->p) {
339     eventlog(eventlog_level_error,__FUNCTION__,"packet_create failed");
340     return -1;
341     }
342     memcpy(&bp->tv,&packettime,sizeof(struct timeval));
343     packet_set_size(bp->p,len);
344     memcpy(packet_get_raw_data(bp->p,0),data,len);
345     bnpcap_conn_add_packet(c,bp);
346     if ((packet_get_class(bp->p)==packet_class_file)&&(packet_get_type(bp->p)==SERVER_FILE_REPLY)) {
347     eventlog(eventlog_level_debug,__FUNCTION__,"file transfer initiated (setting to raw)");
348     bnpcap_conn_set_class(c,packet_class_raw);
349     }
350     } else {
351     /* read out saved state */
352     if (bnpcap_conn_get_dir(c,&s,&d)==packet_dir_from_client) {
353     p = c->clientpkt;
354     off = c->clientoff;
355     } else {
356     p = c->serverpkt;
357     off = c->serveroff;
358     }
359     while ((datap-data)<(signed)len) {
360     if (!p) {
361     eventlog(eventlog_level_debug,__FUNCTION__,"creating new packet");
362     p = packet_create(bnpcap_conn_get_class(c));
363     if (!p) {
364     eventlog(eventlog_level_error,__FUNCTION__,"packet_create failed");
365     return -1;
366     }
367     packet_set_size(p,packet_get_header_size(p)); /* set it to the minimum for now */
368     off = 0;
369     }
370     if (off < packet_get_header_size(p)) {
371     unsigned int l = (packet_get_header_size(p)-off);
372     /* (len-(datap-data)) : remaining bytes in buffer */
373     if ((len-(datap-data)) < l)
374     l = (len-(datap-data));
375     eventlog(eventlog_level_debug,__FUNCTION__,"filling up header (adding %d to %d to get %d)",l,off,packet_get_header_size(p));
376     memcpy(packet_get_raw_data(p,off),datap,l);
377     datap = datap + l;
378     off = off + l;
379     } else {
380     unsigned int l = (packet_get_size(p)-off);
381     if ((len-(datap-data)) < l)
382     l = (len-(datap-data));
383     eventlog(eventlog_level_debug,__FUNCTION__,"filling up packet (0x%04x:%s) (adding %d to %d to get %d)",packet_get_type(p),packet_get_type_str(p,bnpcap_conn_get_dir(c,&s,&d)),l,off,packet_get_size(p));
384     memcpy(packet_get_raw_data(p,off),datap,l);
385     datap = datap + l;
386     off = off + l;
387     }
388     if ((off>=packet_get_header_size(p))&&(off>=packet_get_size(p))) {
389     /* packet is complete */
390     eventlog(eventlog_level_debug,__FUNCTION__,"packet is complete");
391     bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */
392     if (!bp) {
393     eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno));
394     return -1;
395     }
396     if ((off != packet_get_size(p))&&(bnpcap_dodebug)) {
397     eventlog(eventlog_level_warn,__FUNCTION__,"packet size differs (%d != %d) (offset=0x%04x)",off,packet_get_size(p),datap-data);
398     hexdump(stderr,data,len);
399     /* memcpy(packet_get_raw_data(p,0),data,packet_get_size(p)); */
400     }
401     bp->dir = bnpcap_conn_get_dir(c,&s,&d);
402     bp->p = p;
403     bp->id = current_packet_id++;
404     memcpy(&bp->tv,&packettime,sizeof(struct timeval));
405     bnpcap_conn_add_packet(c,bp);
406     if (packet_get_size(p)==0)
407     datap = data + len; /* if size is invalid, drop the rest of the stream packet */
408     p = NULL;
409     off = 0;
410     }
411     } /* while */
412     /* write back saved state */
413     if ((off>0)&&(bnpcap_dodebug)) {
414     eventlog(eventlog_level_debug,__FUNCTION__,"saving %d bytes in packet buffer (p=0x%08x)",off,(int)p);
415     }
416     if (bnpcap_conn_get_dir(c,&s,&d)==packet_dir_from_client) {
417     c->clientpkt = p;
418     c->clientoff = off;
419     } else {
420     c->serverpkt = p;
421     c->serveroff = off;
422     }
423     } /* !always_complete */
424     return 0;
425     }
426     return 0;
427     }
428    
429    
430     /************************************************************************/
431     /******************************** LAYERS ********************************/
432    
433     /********************************* TCP **********************************/
434    
435     static int bnpcap_tcp2tcp(t_tcp_header * d, t_tcp_header_raw const * s)
436     {
437     d->sport = htons(s->sport);
438     d->dport = htons(s->dport);
439     d->seqno = htonl(s->seqno);
440     d->ackno = htonl(s->ackno);
441     d->doffset = (htons(s->stuff) & 0xF000) >> 12;
442     d->flags = (htons(s->stuff) & 0x0FFF);
443     d->window = htons(s->window);
444     d->checksum = htons(s->checksum);
445     d->urgp = htons(s->urgp);
446     return 0;
447     }
448    
449     static int bnpcap_process_tcp(t_ip_header const * ip, unsigned char const *data, unsigned int len)
450     {
451     t_tcp_header_raw const *raw;
452     t_tcp_header h;
453    
454     raw = (t_tcp_header_raw const *) data; /* avoid warning */
455     bnpcap_tcp2tcp(&h,raw);
456     if (h.doffset < 5) {
457     eventlog(eventlog_level_warn,__FUNCTION__,"tcp header too small (%u 32-bit words)",h.doffset);
458     return 1;
459     } else {
460     char fstr[32] = "";
461    
462     if (h.flags & TCP_URG)
463     strcat(fstr,"U");
464     if (h.flags & TCP_ACK)
465     strcat(fstr,"A");
466     if (h.flags & TCP_PSH)
467     strcat(fstr,"P");
468     if (h.flags & TCP_RST)
469     strcat(fstr,"R");
470     if (h.flags & TCP_SYN)
471     strcat(fstr,"S");
472     if (h.flags & TCP_FIN)
473     strcat(fstr,"F");
474     eventlog(eventlog_level_debug,__FUNCTION__,"tcp: sport=%u dport=%u seqno=0x%08x ackno=0x%08x window=0x%08x len=%d (%s)",h.sport,h.dport,h.seqno,h.ackno,h.window,((signed)len-(h.doffset*4)),fstr);
475     if (((signed)len-(h.doffset*4))<=0) {
476     eventlog(eventlog_level_info,__FUNCTION__,"empty packet (%d)",((signed)len-(h.doffset*4)));
477     /* handle sync packets */
478     if (h.flags & TCP_SYN) {
479     t_bnpcap_addr s,d;
480    
481     s.ip=ip->src; s.port=h.sport;
482     d.ip=ip->dst; d.port=h.dport;
483     if (h.flags & TCP_ACK) {
484     t_bnpcap_conn *c = bnpcap_conn_find(&s,&d);
485    
486     if (c) {
487     if (c->tcpstate==tcp_state_syn)
488     c->tcpstate=tcp_state_ack;
489     }
490     } else {
491     if (!bnpcap_conn_find(&s,&d)) {
492     t_bnpcap_conn *c;
493    
494     c = bnpcap_conn_new(&s,&d);
495     c->tcpstate = tcp_state_syn;
496     list_append_data(conns,c);
497     eventlog(eventlog_level_debug,__FUNCTION__,"created new connection with SYN");
498     } else {
499     eventlog(eventlog_level_debug,__FUNCTION__,"got SYN in connection");
500     }
501     }
502     }
503     } else if (((h.sport!=listen_port)&&(h.dport!=listen_port)) && ((h.sport!=6200)&&(h.dport!=6200))) {
504     eventlog(eventlog_level_info,__FUNCTION__,"other packet (%d)",((signed)len-(h.doffset*4)));
505     } else {
506     eventlog(eventlog_level_info,__FUNCTION__,"valid packet (%d)",((signed)len-(h.doffset*4)));
507     bnpcap_conn_packet(ip->src,h.sport,ip->dst,h.dport,data+(h.doffset*4),len-(h.doffset*4));
508     }
509     return 0;
510     }
511     }
512    
513     /************************************ UDP ********************************/
514    
515     static int bnpcap_udp2udp(t_ip_udp_header *d, t_ip_udp_header_raw const *s)
516     {
517     d->sport = ntohs(s->sport);
518     d->dport = ntohs(s->dport);
519     d->len = ntohs(s->len);
520     d->checksum = ntohs(s->checksum);
521     return 0;
522     }
523    
524     static int bnpcap_process_udp(unsigned char const *data, unsigned int len)
525     {
526     t_ip_udp_header_raw const *raw;
527     t_ip_udp_header h;
528     t_bnpcap_packet *bp;
529    
530     raw = (t_ip_udp_header_raw const *) data; /* avoid warning */
531     bnpcap_udp2udp(&h,raw);
532    
533     bp = (t_bnpcap_packet *) malloc(sizeof(t_bnpcap_packet)); /* avoid warning */
534     if (!bp) {
535     eventlog(eventlog_level_error,__FUNCTION__,"malloc failed: %s",pstrerror(errno));
536     return -1;
537     }
538     if (h.dport==listen_port || h.dport==6200) {
539     bp->dir = packet_dir_from_client;
540     } else {
541     bp->dir = packet_dir_from_server;
542     }
543     eventlog(eventlog_level_debug,__FUNCTION__,"sport=%u dport=%u len=%u(%d)",h.sport,h.dport,h.len,len);
544     bp->id = current_packet_id++;
545     memcpy(&bp->tv,&packettime,sizeof(struct timeval));
546     bp->p = packet_create(packet_class_udp);
547     if (!bp->p) {
548     eventlog(eventlog_level_error,__FUNCTION__,"packet_create failed");
549     return -1;
550     }
551     packet_set_size(bp->p,h.len-sizeof(t_ip_udp_header_raw));
552     memcpy(packet_get_raw_data(bp->p,0),data+sizeof(t_ip_udp_header_raw),h.len-sizeof(t_ip_udp_header_raw));
553     eventlog(eventlog_level_error,__FUNCTION__,"id=%u ",bp->id);
554     list_append_data(udppackets,bp);
555     return 0;
556     }
557    
558     /************************************ IP *********************************/
559    
560     static int bnpcap_ip2ip(t_ip_header * d, t_ip_header_raw const * s)
561     {
562     d->version = ((s->versionihl & 0xf0) >> 4);
563     d->ihl = s->versionihl & 0x0f;
564     d->tos = s->tos;
565     d->len = ntohs(s->len);
566     d->id = ntohs(s->id);
567     d->offset = ntohl(s->flagsoffset);
568     d->flags = ((d->offset & 0xE000)>>13);
569     d->offset = ((d->offset & 0x1FFF));
570     d->ttl = s->ttl;
571     d->protocol = s->protocol;
572     d->checksum = ntohs(s->checksum);
573     d->src = ntohl(s->src);
574     d->dst = ntohl(s->dst);
575     return 0;
576     }
577    
578    
579     static int bnpcap_process_ip(unsigned char const *data, unsigned int len)
580     {
581     /* FIXME: handle IP fragmentation */
582     /* FIXME: use identification field to pass the datagram in the right order */
583     t_ip_header_raw const *raw;
584     t_ip_header h;
585    
586     raw = (t_ip_header_raw const *) data; /* avoid warning */
587     bnpcap_ip2ip(&h,raw);
588     if (h.version != 4) {
589     eventlog(eventlog_level_warn,__FUNCTION__,"ip version %u not supported (ihl=%u, raw=0x%02x)",h.version,h.ihl,raw->versionihl);
590     return 1;
591     } else if (h.ihl < 5) {
592     /* an IP header must be at least 5 words */
593     eventlog(eventlog_level_warn,__FUNCTION__,"ip header to small (%u 32-bit words)",h.ihl);
594     return 1;
595     } else if (h.len > len) {
596     eventlog(eventlog_level_warn,__FUNCTION__,"ip len larger than packet (%d > %d)",h.len,len);
597     return 1;
598     } else {
599     char fstr[32] = "";
600    
601     if (h.flags & IP_DF)
602     strcat(fstr,"D");
603     if (h.flags & IP_MF)
604     strcat(fstr,"M");
605     eventlog(eventlog_level_debug,__FUNCTION__,"ip: len=%u(%u) src=%08x dst=%08x protocol=%u offset=0x%08x id=0x%08x (%s)",h.len,len,h.src,h.dst,h.protocol,h.offset,h.id,fstr);
606     if (h.protocol==6) {
607     /* This is TCP */
608     return bnpcap_process_tcp(&h,data+(h.ihl*4),h.len-(h.ihl*4));
609     } else if (h.protocol==17) {
610     /* This is UDP */
611     return bnpcap_process_udp(data+(h.ihl*4),h.len-(h.ihl*4));
612     }
613     }
614     return 0;
615     }
616    
617     /************************************* ETHERNET ******************************/
618    
619     static int bnpcap_process_ether(unsigned char const *data, unsigned int len)
620     { /* Well, first parse the ethernet header (I hope you use Ethernet_II :) ... */
621     t_ether_raw const *raw;
622    
623     raw = (t_ether_raw const *) data; /* avoid warning */
624     if (ntohs(raw->type)==0x0800) {
625     /* This is IP */
626     return bnpcap_process_ip(data+sizeof(t_ether_raw),len-sizeof(t_ether_raw));
627     } else {
628     eventlog(eventlog_level_warn,__FUNCTION__,"unsupported protocol 0x%04x",ntohs(raw->type));
629     return 1;
630     }
631     }
632    
633     /* If you want to use other hardware protocols like PPP add them here ... */
634    
635     /**************************** PACKET/PCAP *********************************/
636    
637     static void bnpcap_process_packet(u_char * private, const struct pcap_pkthdr * p, u_char const * data)
638     {
639     unsigned int pl = p->len;
640    
641     if(private) private = NULL; // hack to eliminate compiler warning
642    
643     memcpy(&packettime,&p->ts,sizeof(struct timeval));
644     eventlog(eventlog_level_debug,__FUNCTION__,"packet: len=%d caplen=%d",p->len,p->caplen);
645     /* FIXME: check if it's ethernet */
646     bnpcap_process_ether(data,pl);
647     }
648    
649     /**************************************************************************/
650    
651     static void bnpcap_usage(void) {
652     printf("BNPCAP - A tool to convert pcap battle.net dumps to a human-readable format.\n");
653     printf("Version " PVPGN_VERSION " --- Copyright (c) 2001 Marco Ziech (mmz@gmx.net)\n");
654     printf("This software makes use of libpcap.\n\n");
655     printf("Usage: bnpcap [-d] [-v] [-p PORT] <pcap-filename>\n");
656     printf(" -d Print out debugging information\n");
657     printf(" -v Be more verbose\n");
658     printf(" -p PORT Specify port to process (Default: 6112)\n\n");
659     }
660    
661     /******************************* MAIN *************************************/
662    
663     int main (int argc, char **argv) {
664     t_elem * currconn;
665     t_elem * currudp;
666     int c;
667    
668     while ((c=getopt(argc,argv,"dvp:"))!=-1) {
669     switch (c) {
670     case 'p':
671     str_to_uint(optarg, &listen_port);
672     break;
673     case 'd':
674     bnpcap_dodebug = 1;
675     break;
676     case 'v':
677     bnpcap_beverbose = 1;
678     break;
679     case '?':
680     printf("unrecognized option '%c'\n",optopt);
681     break;
682     default:
683     printf("getopt returned \'%c\'\n",c);
684     }
685     }
686    
687     if (optind < argc) {
688     filename = argv[optind];
689     } else {
690     bnpcap_usage();
691     return 1;
692     }
693    
694     pc = pcap_open_offline(filename,ebuf);
695     if (!pc) {
696     fprintf(stderr,"pcap_open_offline: %s\n",ebuf);
697     return -1;
698     }
699    
700     eventlog_set(stderr);
701     eventlog_clear_level();
702     if (bnpcap_dodebug)
703     eventlog_add_level("debug");
704     if (bnpcap_beverbose||bnpcap_dodebug)
705     eventlog_add_level("info");
706     eventlog_add_level("warn");
707     eventlog_add_level("error");
708     eventlog_add_level("fatal");
709    
710     conns = list_create();
711     udppackets = list_create();
712     pcap_dispatch(pc,0,bnpcap_process_packet,NULL);
713    
714     printf("### This packet dump was created by bnpcap.\n");
715     LIST_TRAVERSE(conns,currconn) {
716     t_bnpcap_conn *c;
717     char cstr[64];
718     char sstr[64];
719     t_elem * currpacket;
720    
721     c = elem_get_data(currconn);
722     snprintf(cstr,64,"%u.%u.%u.%u:%u",((c->client.ip & 0xFF000000)>>24),((c->client.ip & 0x00FF0000)>>16),((c->client.ip & 0x0000FF00)>>8),((c->client.ip & 0x000000FF)),c->client.port);
723     snprintf(sstr,64,"%u.%u.%u.%u:%u",((c->server.ip & 0xFF000000)>>24),((c->server.ip & 0x00FF0000)>>16),((c->server.ip & 0x0000FF00)>>8),((c->server.ip & 0x000000FF)),c->server.port);
724     printf("## %s connection: client=%s server=%s\n",(c->incomplete?"incomplete":"complete"),cstr,sstr);
725     LIST_TRAVERSE(c->packets,currpacket) {
726     t_bnpcap_packet * bp;
727    
728     bp = elem_get_data(currpacket);
729     printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n",bp->id/*bp->tv.tv_sec*/,(bp->dir==packet_dir_from_client?"client":"server"),packet_get_type(bp->p),packet_get_type_str(bp->p,bp->dir),packet_get_size(bp->p),packet_get_class_str(bp->p));
730     hexdump(stdout,packet_get_raw_data(bp->p,0),packet_get_size(bp->p));
731     printf("\n");
732     }
733     }
734     printf("## udp packets\n");
735     LIST_TRAVERSE(udppackets,currudp) {
736     t_bnpcap_packet *bp;
737    
738     bp = elem_get_data(currudp);
739     printf("# %u packet from %s: type=0x%04x(%s) length=%d class=%s\n",bp->id/*bp->tv.tv_sec*/,(bp->dir==packet_dir_from_client?"client":"server"),packet_get_type(bp->p),packet_get_type_str(bp->p,bp->dir),packet_get_size(bp->p),packet_get_class_str(bp->p));
740     hexdump(stdout,packet_get_raw_data(bp->p,0),packet_get_size(bp->p));
741     printf("\n");
742     }
743     pcap_close(pc);
744     return 0;
745     }
746    

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1