1/*
2 * pptpgre.c
3 *
4 * originally by C. S. Ananian
5 * Modified for PoPToP
6 *
7 * $Id: pptpgre.c,v 1.9 2007/04/16 00:21:02 quozl Exp $
8 */
9
10#ifdef HAVE_CONFIG_H
11#include "config.h"
12#endif
13
14#ifdef __linux__
15#define _GNU_SOURCE 1		/* broken arpa/inet.h */
16#endif
17
18#include "our_syslog.h"
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <sys/types.h>
23#include <sys/socket.h>
24#include <netinet/in.h>
25#include <arpa/inet.h>
26#include <sys/stat.h>
27#include <time.h>
28#include <sys/time.h>
29#include <unistd.h>
30#include <string.h>
31#include <errno.h>
32#include <fcntl.h>
33#ifdef HAVE_SYS_UIO_H
34#include <sys/uio.h>
35#endif
36
37#include "ppphdlc.h"
38#include "pptpgre.h"
39#include "pptpdefs.h"
40#include "pptpctrl.h"
41#include "defaults.h"
42#include "pqueue.h"
43
44#ifndef HAVE_STRERROR
45#include "compat.h"
46#endif
47
48#define PACKET_MAX 8196
49
50typedef int (*callback_t)(int cl, void *pack, unsigned int len);
51
52/* test for a 32 bit counter overflow */
53#define WRAPPED( curseq, lastseq) \
54    ((((curseq) & 0xffffff00) == 0) && \
55     (((lastseq) & 0xffffff00 ) == 0xffffff00))
56
57static struct gre_state gre;
58gre_stats_t stats;
59
60static uint64_t time_now_usecs()
61{
62    struct timeval tv;
63    gettimeofday(&tv, NULL);
64    return (tv.tv_sec * 1000000) + tv.tv_usec;
65}
66
67int pptp_gre_init(u_int32_t call_id_pair, int pty_fd, struct in_addr *inetaddrs)
68{
69	struct sockaddr_in addr;
70	int gre_fd;
71
72	/* Open IP protocol socket */
73	gre_fd = socket(AF_INET, SOCK_RAW, PPTP_PROTO);
74	if (gre_fd < 0) {
75		syslog(LOG_ERR, "GRE: socket() failed");
76		return -1;
77	}
78
79	memset(&addr, 0, sizeof(addr));
80
81	addr.sin_family = AF_INET;
82	addr.sin_addr = inetaddrs[0];
83	addr.sin_port = 0;
84	if (bind(gre_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
85		syslog(LOG_ERR, "GRE: bind() failed: %s", strerror(errno));
86		syslog(LOG_ERR, "GRE: continuing, but may not work if multi-homed");
87	}
88
89	addr.sin_family = AF_INET;
90	addr.sin_addr = inetaddrs[1];
91	addr.sin_port = 0;
92	if (connect(gre_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
93		syslog(LOG_ERR, "GRE: connect() failed: %s", strerror(errno));
94		return -1;
95	}
96
97	gre.seq_sent = 0;
98	gre.ack_sent = gre.ack_recv = gre.seq_recv = 0xFFFFFFFF;
99	/* seq_recv is -1, therefore next packet expected is seq 0,
100	   to comply with RFC 2637: 'The sequence number for each
101	   user session is set to zero at session startup.' */
102
103	gre.call_id_pair = call_id_pair;	       /* network byte order */
104	return gre_fd;
105}
106
107/* ONE blocking read per call; dispatches all packets possible */
108/* returns 0 on success, or <0 on read failure                 */
109int decaps_hdlc(int fd, int (*cb) (int cl, void *pack, unsigned len), int cl)
110{
111	static unsigned char buffer[PACKET_MAX], copy[PACKET_MAX];
112	static unsigned start = 0, end = 0;
113	static unsigned len = 0, escape = 0;
114	static u_int16_t fcs = PPPINITFCS16;
115	static unsigned char err = 0;
116	unsigned char c;
117	int status;
118
119	/* we do one read only, since it may block.  and only if the
120	 * buffer is empty (start == end)
121	 */
122
123	if (fd == -1) {
124		if(cb == NULL) {
125			/* peek mode */
126			return err ? -1 : 0;
127		} else if (!err) {
128			/* re-xmit and nothing queued */
129			syslog(LOG_ERR, "GRE: Re-xmit called with nothing queued");
130			return -1;
131		}
132	}
133
134	if (!err) {
135		/* All known data is processed.  This true unless the last
136		 * network write failed.
137		 */
138		if ((status = read(fd, buffer, sizeof(buffer))) <= 0) {
139			syslog(LOG_ERR, "GRE: read(fd=%d,buffer=%lx,len=%d) from PTY failed: status = %d error = %s%s",
140			       fd, (unsigned long) buffer, sizeof(buffer),
141			       status, status ? strerror(errno) : "No error",
142			       errno != EIO ? "" : ", usually caused by unexpected termination of pppd, check option syntax and pppd logs");
143			/* FAQ: mistakes in pppd option spelling in
144			 * /etc/ppp/options.pptpd often cause EIO,
145			 * with pppd not reporting the problem to any
146			 * logs.  Termination of pppd by signal can
147			 * *also* cause this situation. -- James Cameron
148			 */
149			return -1;
150		}
151		end = status;
152		start = 0;
153	} else {
154		/* We're here because of a network write failure.  Try again.
155		 * Then do what we would do normally and enter the loop as if
156		 * just continuing the while(1).  Not sure that this ever
157		 * really happens, but since we error-check status then we
158		 * should have the code to handle an error :-)
159		 */
160		err = 0;
161		if ((status = cb(cl, copy, len)) < 0) {
162			syslog(LOG_ERR, "GRE: re-xmit failed from decaps_hdlc: %s", strerror(errno));
163			err = 1;
164			return status;	/* return error */
165		}
166		/* Great!  Let's do more! */
167		fcs = PPPINITFCS16;
168		len = 0;
169		escape = 0;
170	}
171
172	while (1) {
173		/* Infinite loop, we return when we're out of data */
174
175		/* Check if out of data */
176		if (start == end)
177			return 0;
178
179		/* Add to the packet up till the next HDLC_FLAG (start/end of
180		 * packet marker).  Copy to 'copy', un-escape and checksum as we go.
181		 */
182		while (buffer[start] != HDLC_FLAG) {
183
184			/* Dispose of 'too long' packets */
185			if (len >= PACKET_MAX) {
186				syslog(LOG_ERR, "GRE: Received too long packet from pppd.");
187				while (buffer[start] != HDLC_FLAG && start < end)
188					start++;
189				if (start < end) {
190					goto newpacket;
191				} else
192					return 0;
193			}
194			/* Read a character, un-escaping if needed */
195			if (buffer[start] == HDLC_ESCAPE && !escape)
196				escape = 1;
197			else {
198				if (escape) {
199					copy[len] = c = buffer[start] ^ 0x20;
200					escape = 0;
201				} else
202					copy[len] = c = buffer[start];
203				fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
204				len++;
205			}
206			start++;
207
208			/* Check if out of data */
209			if (start == end)
210				return 0;
211		}
212
213		/* Found flag.  Skip past it */
214		start++;
215
216		/* Check for over-short packets and silently discard, as per RFC1662 */
217		if ((len < 4) || (escape == 1)) {
218			/* len == 0 is possible, we generate it :-) [using HDLC_ESCAPE at
219			 * start and end of packet].  Others are worth recording.
220			 */
221			if (len && len < 4)
222				syslog(LOG_ERR, "GRE: Received too short packet from pppd.");
223			if (escape)
224				syslog(LOG_ERR, "GRE: Received bad packet from pppd.");
225			goto newpacket;
226		}
227		/* Check, then remove the 16-bit FCS checksum field */
228		if (fcs != PPPGOODFCS16) {
229			syslog(LOG_ERR, "GRE: Bad checksum from pppd.");
230			goto newpacket;
231		}
232		len -= sizeof(u_int16_t);
233
234		/* So now we have a packet of length 'len' in 'copy' */
235		if ((status = cb(cl, copy, len)) < 0) {
236			syslog(LOG_ERR, "GRE: xmit failed from decaps_hdlc: %s", strerror(errno));
237			err = 1;
238			return status;	/* return error */
239		}
240	      newpacket:
241		/* Great!  Let's do more! */
242		fcs = PPPINITFCS16;
243		len = 0;
244		escape = 0;
245	}
246}
247
248#define seq_greater(A,B) ((A)>(B) || \
249                         (((u_int32_t)(A)<0xff) && ((~((u_int32_t)(B)))<0xff)))
250
251/* Macro used in encaps_hdlc().  add "val" to "dest" at position "pos",
252 * incrementing "pos" to point after the added value.  set "tmp" to "val"
253 * as a side-effect.
254 */
255#define ADD_CHAR(dest, pos, val, tmp) \
256	tmp = (val); \
257	if ((tmp<0x20) || (tmp==HDLC_FLAG) || (tmp==HDLC_ESCAPE)) { \
258		dest[pos++]=HDLC_ESCAPE; \
259		dest[pos++]=tmp^0x20; \
260	} else \
261		dest[pos++]=tmp
262
263/* Make stripped packet into HDLC packet */
264int encaps_hdlc(int fd, void *pack, unsigned len)
265{
266	unsigned char *source = (unsigned char *) pack;
267	/* largest expansion possible - double all + double fcs + 2 flags */
268	static unsigned char dest[2 * PACKET_MAX + 6];
269	unsigned pos = 1, i;
270	u_int16_t fcs;
271	unsigned char c;
272
273	fcs = PPPINITFCS16;
274
275	/* make sure overflow is impossible so we don't have to bounds check
276	 * in loop.  drop large packets.
277	 */
278	if (len > PACKET_MAX) {
279		syslog(LOG_ERR, "GRE: Asked to encapsulate too large packet (len = %d)", len);
280		return -1;
281	}
282	/* start character */
283	dest[0] = HDLC_FLAG;
284
285	/* escape the payload */
286	for (i = 0; i < len; i++) {
287		ADD_CHAR(dest, pos, source[i], c);
288		fcs = (fcs >> 8) ^ fcstab[(fcs ^ c) & 0xff];
289	}
290
291	fcs ^= 0xFFFF;
292
293	ADD_CHAR(dest, pos, fcs & 0xFF, c);
294	ADD_CHAR(dest, pos, fcs >> 8, c);
295
296	/* tack on the end-flag */
297	dest[pos++] = HDLC_FLAG;
298
299	/* now write this packet */
300	return write(fd, dest, pos);
301}
302
303#undef ADD_CHAR
304
305
306static int dequeue_gre (callback_t callback, int cl)
307{
308	pqueue_t *head;
309	int status;
310	/* process packets in the queue that either are expected or
311	   have timed out. */
312	head = pqueue_head();
313	while ( head != NULL &&
314		( (head->seq == gre.seq_recv + 1) || /* wrap-around safe */
315		  (pqueue_expiry_time(head) <= 0)
316		  )
317		) {
318		/* if it is timed out... */
319		if (head->seq != gre.seq_recv + 1 ) {  /* wrap-around safe */
320			stats.rx_lost += head->seq - gre.seq_recv - 1;
321			if (pptpctrl_debug)
322				syslog(LOG_DEBUG,
323				       "GRE: timeout waiting for %d packets",
324				       head->seq - gre.seq_recv - 1);
325		}
326		if (pptpctrl_debug)
327			syslog(LOG_DEBUG, "GRE: accepting #%d from queue",
328			       head->seq);
329		gre.seq_recv = head->seq;
330		status = callback(cl, head->packet, head->packlen);
331		pqueue_del(head);
332		if (status < 0) return status;
333		head = pqueue_head();
334	}
335	return 0;
336}
337
338
339int decaps_gre(int fd, int (*cb) (int cl, void *pack, unsigned len), int cl)
340{
341	static unsigned char buffer[PACKET_MAX + 64 /*ip header */ ];
342	struct pptp_gre_header *header;
343	int status, ip_len = 0;
344
345	dequeue_gre(cb, cl);
346	if ((status = read(fd, buffer, sizeof(buffer))) <= 0) {
347		syslog(LOG_ERR, "GRE: read(fd=%d,buffer=%lx,len=%d) from network failed: status = %d error = %s",
348		       fd, (unsigned long) buffer, sizeof(buffer), status, status ? strerror(errno) : "No error");
349		stats.rx_errors++;
350		return -1;
351	}
352	/* strip off IP header, if present */
353	if ((buffer[0] & 0xF0) == 0x40)
354		ip_len = (buffer[0] & 0xF) * 4;
355	header = (struct pptp_gre_header *) (buffer + ip_len);
356
357	/* verify packet (else discard) */
358	if (((ntoh8(header->ver) & 0x7F) != PPTP_GRE_VER) ||	/* version should be 1   */
359	    (ntoh16(header->protocol) != PPTP_GRE_PROTO) ||	/* GRE protocol for PPTP */
360	    PPTP_GRE_IS_C(ntoh8(header->flags)) ||	/* flag C should be clear   */
361	    PPTP_GRE_IS_R(ntoh8(header->flags)) ||	/* flag R should be clear   */
362	    (!PPTP_GRE_IS_K(ntoh8(header->flags))) ||	/* flag K should be set     */
363	    ((ntoh8(header->flags) & 0xF) != 0)) {	/* routing and recursion ctrl = 0  */
364		/* if invalid, discard this packet */
365		syslog(LOG_ERR, "GRE: Discarding packet by header check");
366		stats.rx_invalid++;
367		return 0;
368	}
369	if (header->call_id != GET_VALUE(PAC, gre.call_id_pair)) {
370                /*
371                 * Discard silently to allow more than one GRE tunnel from
372                 * the same IP address in case clients are behind the
373                 * firewall.
374                 *
375                 * syslog(LOG_ERR, "GRE: Discarding for incorrect call");
376                 */
377		return 0;
378	}
379	if (PPTP_GRE_IS_A(ntoh8(header->ver))) {	/* acknowledgement present */
380		u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags))) ?
381			ntoh32(header->ack) : ntoh32(header->seq);
382			/* ack in different place if S=0 */
383
384		if (seq_greater(ack, gre.ack_recv))
385			gre.ack_recv = ack;
386
387		/* also handle sequence number wrap-around  */
388		if (WRAPPED(ack,gre.ack_recv)) gre.ack_recv = ack;
389		if (gre.ack_recv == stats.pt.seq) {
390			int rtt = time_now_usecs() - stats.pt.time;
391			stats.rtt = (stats.rtt + rtt) / 2;
392		}
393	}
394	if (PPTP_GRE_IS_S(ntoh8(header->flags))) {	/* payload present */
395		unsigned headersize = sizeof(*header);
396		unsigned payload_len = ntoh16(header->payload_len);
397		u_int32_t seq = ntoh32(header->seq);
398
399		if (!PPTP_GRE_IS_A(ntoh8(header->ver)))
400			headersize -= sizeof(header->ack);
401		/* check for incomplete packet (length smaller than expected) */
402		if (status - headersize < payload_len) {
403			stats.rx_truncated++;
404			return 0;
405		}
406		/* check for out-of-order sequence number */
407		if (seq == gre.seq_recv + 1) {
408			if (pptpctrl_debug)
409				syslog(LOG_DEBUG, "GRE: accepting packet #%d",
410				       seq);
411			stats.rx_accepted++;
412			gre.seq_recv = seq;
413			return cb(cl, buffer + ip_len + headersize, payload_len);
414		} else if (seq == gre.seq_recv) {
415			if (pptpctrl_debug)
416				syslog(LOG_DEBUG,
417				       "GRE: discarding duplicate or old packet #%d (expecting #%d)",
418				       seq, gre.seq_recv + 1);
419			return 0;	/* discard duplicate packets */
420		} else {
421			stats.rx_buffered++;
422			if (pptpctrl_debug)
423				syslog(LOG_DEBUG,
424				       "GRE: buffering packet #%d (expecting #%d, lost or reordered)",
425				       seq, gre.seq_recv + 1);
426			pqueue_add(seq, buffer + ip_len + headersize, payload_len);
427			return 0;	/* discard out-of-order packets */
428		}
429	}
430	return 0;		/* ack, but no payload */
431}
432
433
434int encaps_gre(int fd, void *pack, unsigned len)
435{
436	static union {
437		struct pptp_gre_header header;
438		unsigned char buffer[PACKET_MAX + sizeof(struct pptp_gre_header)];
439	} u;
440	unsigned header_len;
441#ifdef HAVE_WRITEV
442	struct iovec iovec[2];
443#endif
444
445	if(fd == -1)
446		/* peek mode */
447		return (gre.ack_sent == gre.seq_recv) ? 0 : -1;
448
449	/* package this up in a GRE shell. */
450	u.header.flags = hton8(PPTP_GRE_FLAG_K);
451	u.header.ver = hton8(PPTP_GRE_VER);
452	u.header.protocol = hton16(PPTP_GRE_PROTO);
453	u.header.payload_len = hton16(len);
454	u.header.call_id = GET_VALUE(PNS, gre.call_id_pair);
455
456	/* special case ACK with no payload */
457	if (pack == NULL) {
458		if (gre.ack_sent != gre.seq_recv) {
459			u.header.ver |= hton8(PPTP_GRE_FLAG_A);
460			u.header.payload_len = hton16(0);
461			u.header.seq = hton32(gre.seq_recv);	/* ack is in odd place because S=0 */
462			gre.ack_sent = gre.seq_recv;
463			/* don't sent ACK field, ACK is in SYN field */
464			return write(fd, u.buffer, sizeof(u.header) - sizeof(u.header.ack));
465		} else
466			return 0;	/* we don't need to send ACK */
467	}
468	/* send packet with payload */
469	u.header.flags |= hton8(PPTP_GRE_FLAG_S);
470	u.header.seq = hton32(gre.seq_sent);
471	gre.seq_sent++;
472	if (gre.ack_sent != gre.seq_recv) {	/* send ack with this message */
473		u.header.ver |= hton8(PPTP_GRE_FLAG_A);
474		u.header.ack = hton32(gre.seq_recv);
475		gre.ack_sent = gre.seq_recv;
476		header_len = sizeof(u.header);
477	} else {	/* don't send ack */
478		header_len = sizeof(u.header) - sizeof(u.header.ack);
479	}
480	if (len > PACKET_MAX) {
481		syslog(LOG_ERR, "GRE: packet is too large %d", len);
482		stats.tx_oversize++;
483		return 0;	/* drop this, it's too big */
484	}
485#ifdef HAVE_WRITEV
486	/* write header and buffer without copying. */
487	iovec[0].iov_base = u.buffer;
488	iovec[0].iov_len = header_len;
489	iovec[1].iov_base = pack;
490	iovec[1].iov_len = len;
491	return writev(fd, iovec, 2);
492#else
493	/* copy payload into buffer */
494	memcpy(u.buffer + header_len, pack, len);
495	/* record and increment sequence numbers */
496	/* write this baby out to the net */
497	return write(fd, u.buffer, header_len + len);
498#endif
499}
500