All of lore.kernel.org
 help / color / mirror / Atom feed
From: James Carlson <carlsonj@workingcode.com>
To: linux-ppp@vger.kernel.org
Subject: Re: PPP compression
Date: Sat, 20 Dec 2014 21:24:24 +0000	[thread overview]
Message-ID: <5495E908.2090209@workingcode.com> (raw)
In-Reply-To: <3b4526880d737ed5094d632636e6fef8@great.ufc.br>

[-- Attachment #1: Type: text/plain, Size: 578 bytes --]

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@workingcode.com>

[-- Attachment #2: pcap2pppd.c --]
[-- Type: text/x-csrc, Size: 8725 bytes --]

#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;
}

  parent reply	other threads:[~2014-12-20 21:24 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-18 20:49 PPP compression arthurpaulino
2014-12-18 21:24 ` James Carlson
2014-12-19 17:28 ` Arthur Paulino
2014-12-20 21:24 ` James Carlson [this message]
2014-12-21 18:37 ` Michael Richardson
2014-12-22 12:34 ` James Carlson
2014-12-22 18:06 ` arthurpaulino
2014-12-22 19:09 ` James Carlson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5495E908.2090209@workingcode.com \
    --to=carlsonj@workingcode.com \
    --cc=linux-ppp@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.