Re: PPP compression

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 12/19/14 12:28, Arthur Paulino wrote:
> I tried to use pppdump with -p and -d. The input file I used was the
> pcap file (packets.pcap) generated by tcpdump.

As I said, pppdump and pcap formats are not at all the same.  You'll
have to convert to go this route.

Attached is a quick-and-dirty program I wrote to convert from the Linux
libpcap variant and PPTP encapsulation you seem to be using and simple
pppdump format.  I didn't bother with timestamps or other bits.  Maybe
it'll work for you.

-- 
James Carlson         42.703N 71.076W         <carlsonj@xxxxxxxxxxxxxxx>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <inttypes.h>
#include <netinet/in.h>

#define MAGIC 0xa1b2c3d4
#define RMAGIC 0xd4c3b2a1

#define ETHERNET 1
#define LINUX_SLL 113

#define ESCAPED(x)	((x) == 0x7D || (x) == 0x7E)
#define PUTESC(x, o)	\
	if (ESCAPED(x)) { \
		putc(0x7D, (o)); \
		putc((x) ^ 0x20, (o)); \
	} else { \
		putc((x), (o)); \
	}

typedef struct pcap_hdr_s {
        uint32_t magic_number;   /* magic number */
        uint16_t version_major;  /* major version number */
        uint16_t version_minor;  /* minor version number */
        int32_t  thiszone;       /* GMT to local correction */
        uint32_t sigfigs;        /* accuracy of timestamps */
        uint32_t snaplen;        /* max length of captured packets, in octets */
        uint32_t network;        /* data link type */
} pcap_hdr_t;

typedef struct pcaprec_hdr_s {
	uint32_t ts_sec;
	uint32_t ts_usec;
	uint32_t incl_len;
	uint32_t orig_len;
} pcaprec_hdr_t;

typedef struct linux_sll_s {
	uint16_t packettype;	/* big endian */
	uint16_t arphrd;	/* big endian */
	uint16_t ll_addr_len;	/* big endian */
	uint8_t ll_addr[8];
	uint16_t protocoltype;	/* big endian */
} linux_sll_t;

#define PROTO_IP 0x0800
#define PROTO_PPP 0x880B

typedef enum {
	to_us = 0,
	bcast_by_other,
	mcast_by_other,
	other_to_other,
	from_us
} ptype_t;

static u_short fcstab[256] = {
	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
};

static void
debug(const char *fmt, ...)
{
#if 0
	va_list ap;

	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
#endif
}

static uint32_t
readu32(uint32_t *vptr, int reversed)
{
	uint32_t value = *vptr;

	if (reversed)
		value = (value << 24) | ((value << 8) & 0xff0000) |
			((value >> 8) & 0xff00) | (value >> 24);
	return value;
}

static void
process(FILE *fin, FILE *fout, char *filename)
{
	pcap_hdr_t hdr;
	size_t rlen, slen;
	int reversed;
	uint32_t network;
	uint8_t *packet;
	uint32_t addr_from = 0; /* arbitrary to/from */

	rlen = fread(&hdr, 1, sizeof (hdr), fin);
	if (rlen < sizeof (hdr)) {
		fprintf(stderr, "pcap2pppd: missing header on %s\n", filename);
		return;
	}
	if (hdr.magic_number == MAGIC) {
		reversed = 0;
	} else if (hdr.magic_number == RMAGIC) {
		reversed = 1;
	} else {
		fprintf(stderr, "pcap2pppd: bad magic number on %s\n", filename);
		return;
	}
	network = readu32(&hdr.network, reversed);
	if (network != LINUX_SLL) {
		fprintf(stderr, "pcap2pppd: unsupported network type %d in %s\n", network, filename);
		return;
	}
	slen = readu32(&hdr.snaplen, reversed);
	if (slen < 1024)
		slen = 1024;
	else if (slen > 65536)
		slen = 65536;
	packet = malloc(slen);
	for (;;) {
		struct {
			pcaprec_hdr_t pcaprec;
			linux_sll_t sll;
		} phdr;
		uint32_t plen;
		int hlen, i;
		uint16_t gtype, ilen, fcs;
		uint32_t ipaddr;

		rlen = fread(&phdr, 1, sizeof (phdr), fin);
		if (rlen < sizeof (phdr))
			break;
		plen = readu32(&phdr.pcaprec.incl_len, reversed);
		if (plen > slen)
			plen = slen;
		/* pcap's packet length includes the Linux SLL header */
		if (plen < sizeof (phdr.sll)) {
			fprintf(stderr, "pcap2pppd: packet without SLL in %s\n", filename);
			break;
		}
		plen -= sizeof (phdr.sll);
		/* now read the actual payload from the file */
		rlen = fread(packet, 1, plen, fin);
		if (rlen < plen) {
			fprintf(stderr, "pcap2pppd: truncated packet at end of %s\n", filename);
			break;
		}
		if (ntohs(phdr.sll.protocoltype) != PROTO_IP) {
			debug("ignore sll proto %d\n",
			      ntohs(phdr.sll.protocoltype));
			continue;
		}
		/* check for IPv4 */
		if ((packet[0] & 0xF0) != 0x40) {
			debug("ignore bad IP type %02x\n", packet[0]);
			continue;
		}
		hlen = (packet[0] & 0xF) << 2;
		if (hlen < 20 || hlen > rlen) {
			debug("ignore bad IP header len %d\n", hlen);
			continue;
		}
		ilen = (packet[2] << 8) + packet[3];
		if (hlen > ilen) {
			debug("ignore bad IP header len %d\n", hlen);
			continue;
		}
		if (ilen > rlen)
			ilen = rlen;
		ipaddr = (packet[12] << 24) | (packet[13] << 16) |
			(packet[14] << 8) | packet[15];
		if (addr_from == 0) {
			debug("arbitrarily choosing %08x as sender.\n", ipaddr);
			addr_from = ipaddr;
		}
		/* check for some form of GRE */
		if (packet[9] != 0x2F) {
			debug("ignore non-GRE protocol %02x\n", packet[9]);
			continue;
		}
		if (ilen < hlen + 2) {
			debug("ignore GRE missing header (%d < %d)\n",
			      ilen, hlen + 2);
			continue;
		}
		/* check for PPTP's non-standard GRE */
		if (!(packet[hlen] & 0x20) || (packet[hlen + 1] & 3) != 1) {
			debug("ignore non-PPTP GRE\n");
			continue;
		}
		gtype = (packet[hlen + 2] << 8) | packet[hlen + 3];
		if (gtype != PROTO_PPP) {
			debug("ignore unexpected GRE payload type %04x\n",
			      gtype);
			continue;
		}
		/* This next line would be correct for real GRE. */
		/* hlen += (packet[hlen] & 0x80) ? 8 : 4; */
		/* This is for Microsoft's weird PPTP GRE. */
		hlen += 8 + ((packet[hlen] & 0x10) ? 4 : 0) +
			((packet[hlen + 1] & 0x80) ? 4 : 0);
		if (ilen <= hlen) {
			debug("ignore GRE without payload\n");
			continue;
		}
		/* Encode the remainder */
		if (phdr.sll.packettype == from_us) {
			putc(0x01, fout);
		} else if (phdr.sll.packettype == to_us) {
			putc(0x02, fout);
		} else {
			putc((ipaddr == addr_from ? 0x01 : 0x02), fout);
		}
		plen = ilen - hlen;
		debug("encoding packet of length %u\n", plen);
		/* first, scan for escapes and add them up */
		fcs = 0xFFFF;
		for (i = hlen; i < ilen; i++) {
			if (ESCAPED(packet[i]))
				plen++;
			fcs = (fcs >> 8) ^ fcstab[(fcs ^ packet[i]) & 0xFF];
		}
		fcs ^= 0xFFFF;
		/* then account for the final FCS and 0x7E */
		plen += 3;
		if (ESCAPED((fcs >> 8) & 0xFF))
			plen++;
		if (ESCAPED(fcs & 0xFF))
			plen++;
		putc((plen >> 8) & 0xFF, fout);
		putc(plen & 0xFF, fout);
		while (hlen < ilen) {
			PUTESC(packet[hlen], fout);
			hlen++;
		}
		PUTESC(fcs & 0xFF, fout);
		PUTESC((fcs >> 8) & 0xFF, fout);
		putc(0x7E, fout);
	}
	free(packet);
}

int
main(int argc, char **argv)
{
	int retv = -1;

	if (argc <= 1) {
		process(stdin, stdout, "stdin");
		retv = 0;
	} else {
		char *filename;
		while ((filename = *++argv) != NULL) {
			FILE *fin = fopen(filename, "r");
			FILE *fout;

			if (fin == NULL) {
				perror(filename);
			} else {
				char *cp = strstr(filename, ".pcap");
				size_t slen = strlen(filename);
				char *oname;

				if (cp != NULL)
					slen = cp - filename;
				oname = malloc(slen + 9);
				strncpy(oname, filename, slen);
				strcpy(oname + slen, ".pppdump");
				fout = fopen(oname, "w");
				if (fout == NULL) {
					perror(oname);
				} else {
					process(fin, fout, filename);
					retv = 0;
					fclose(fout);
				}
				fclose(fin);
				free(oname);
			}
		}
	}
	return retv;
}

[Index of Archives]     [Linux Audio Users]     [Linux for Hams]     [Kernel Newbies]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Samba]     [Video 4 Linux]     [Fedora Users]

  Powered by Linux