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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1.1.1 - (show 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 /*
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