/* msn sniffer 4 newbs */

#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


#ifndef __USE_BSD
#define   __USE_BSD
#endif
#define __FAVOR_BSD

#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

#define E(x)	{ fprintf(stderr, x); exit(-1); }

void dump_bin(unsigned char *p, int l) {
	int i;
	for(i = 0; i < l; i ++) {
		printf("0x%x ", *(p+i));
	}
	return;
}

int main(void)
{
	pcap_t *desc;
	char *dev;
	struct bpf_program fcode;
	bpf_u_int32 netmask, lnet;
	struct pcap_pkthdr hdr;
	unsigned char *pck;
	int r;

	struct ip *ipptr;
	struct tcphdr *tcpptr;
	unsigned char *pckptr;
	unsigned char buffer[4096];
	int len;

#define SERV_TO_CLIENT	1
#define CLIENT_TO_SERV	2

	int sens;

	if(getuid() != 0) {
		E("Need to be root.\n");
	}

	/* get eth0 */
	dev = pcap_lookupdev(NULL);
	if(dev == NULL) {
		E("No dev found.\n");
	}

	desc = pcap_open_live(dev, 1500, 1, 1000, NULL);
	if(desc == NULL) {
		E("Couldn't open device.\n");
	}

	pcap_lookupnet(dev, &lnet, &netmask, NULL);

	r = pcap_compile(desc, &fcode, "tcp and port 1863", 1, netmask);
	if(r < 0) {
		pcap_close(desc);
		E("Can't compile BPF expr.\n");
	}

	r = pcap_setfilter(desc, &fcode);
	if(r < 0) {
		pcap_close(desc);
		E("Can't set filter.\n");
	}

	while(1 == 1) {
		pck = (unsigned char *)pcap_next(desc, &hdr);
		if(pck == NULL)
			continue;

#define TH_OFF(th)      (((th)->th_off & 0xf0) >> 4)

		ipptr = (struct ip*)(pck + 14);
		tcpptr = (struct tcphdr*)(pck + 14 + sizeof(struct ip));
		pckptr = (unsigned char *)(pck + 14 + sizeof(struct ip) + \
				(tcpptr->th_off << 2));

		len = hdr.caplen - (pckptr - pck);

		if(htons(tcpptr->th_sport) == 1863)) {
			sens = SERV_TO_CLIENT;
		} else {
			sens = CLIENT_TO_SERV;
		}

		printf("\n[=====================] Size: %d\n", len);

		if(sens == SERV_TO_CLIENT) {
			printf("Recieved by msn server:\n");
		} else {
			printf("Sent to msn server:\n");
		}

		bzero(buffer, sizeof(buffer));
		strncpy(buffer, pckptr, (len>4095)?4095:len);
		printf("%s\n", buffer);
	}

	pcap_close(desc);

	return 0;
}
