xref: /dragonfly/sys/netgraph/pptpgre/ng_pptpgre.c (revision 6e278935)
1 
2 /*
3  * ng_pptpgre.c
4  *
5  * Copyright (c) 1996-1999 Whistle Communications, Inc.
6  * All rights reserved.
7  *
8  * Subject to the following obligations and disclaimer of warranty, use and
9  * redistribution of this software, in source or object code forms, with or
10  * without modifications are expressly permitted by Whistle Communications;
11  * provided, however, that:
12  * 1. Any and all reproductions of the source or object code must include the
13  *    copyright notice above and the following disclaimer of warranties; and
14  * 2. No rights are granted, in any manner or form, to use Whistle
15  *    Communications, Inc. trademarks, including the mark "WHISTLE
16  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
17  *    such appears in the above copyright notice or in the software.
18  *
19  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
20  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
21  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
22  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
24  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
25  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
26  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
27  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
28  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
29  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
31  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
32  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
35  * OF SUCH DAMAGE.
36  *
37  * Author: Archie Cobbs <archie@freebsd.org>
38  *
39  * $FreeBSD: src/sys/netgraph/ng_pptpgre.c,v 1.2.2.13 2002/10/10 18:27:54 archie Exp $
40  * $Whistle: ng_pptpgre.c,v 1.7 1999/12/08 00:10:06 archie Exp $
41  */
42 
43 /*
44  * PPTP/GRE netgraph node type.
45  *
46  * This node type does the GRE encapsulation as specified for the PPTP
47  * protocol (RFC 2637, section 4).  This includes sequencing and
48  * retransmission of frames, but not the actual packet delivery nor
49  * any of the TCP control stream protocol.
50  *
51  * The "upper" hook of this node is suitable for attaching to a "ppp"
52  * node link hook.  The "lower" hook of this node is suitable for attaching
53  * to a "ksocket" node on hook "inet/raw/gre".
54  */
55 
56 #include <sys/param.h>
57 #include <sys/systm.h>
58 #include <sys/kernel.h>
59 #include <sys/time.h>
60 #include <sys/conf.h>
61 #include <sys/mbuf.h>
62 #include <sys/malloc.h>
63 #include <sys/errno.h>
64 #include <sys/thread2.h>
65 
66 #include <netinet/in.h>
67 #include <netinet/in_systm.h>
68 #include <netinet/ip.h>
69 
70 #include <netgraph/ng_message.h>
71 #include <netgraph/netgraph.h>
72 #include <netgraph/ng_parse.h>
73 #include "ng_pptpgre.h"
74 
75 /* GRE packet format, as used by PPTP */
76 struct greheader {
77 #if BYTE_ORDER == LITTLE_ENDIAN
78 	u_char		recursion:3;		/* recursion control */
79 	u_char		ssr:1;			/* strict source route */
80 	u_char		hasSeq:1;		/* sequence number present */
81 	u_char		hasKey:1;		/* key present */
82 	u_char		hasRoute:1;		/* routing present */
83 	u_char		hasSum:1;		/* checksum present */
84 	u_char		vers:3;			/* version */
85 	u_char		flags:4;		/* flags */
86 	u_char		hasAck:1;		/* acknowlege number present */
87 #elif BYTE_ORDER == BIG_ENDIAN
88 	u_char		hasSum:1;		/* checksum present */
89 	u_char		hasRoute:1;		/* routing present */
90 	u_char		hasKey:1;		/* key present */
91 	u_char		hasSeq:1;		/* sequence number present */
92 	u_char		ssr:1;			/* strict source route */
93 	u_char		recursion:3;		/* recursion control */
94 	u_char		hasAck:1;		/* acknowlege number present */
95 	u_char		flags:4;		/* flags */
96 	u_char		vers:3;			/* version */
97 #else
98 #error BYTE_ORDER is not defined properly
99 #endif
100 	u_int16_t	proto;			/* protocol (ethertype) */
101 	u_int16_t	length;			/* payload length */
102 	u_int16_t	cid;			/* call id */
103 	u_int32_t	data[0];		/* opt. seq, ack, then data */
104 };
105 
106 /* The PPTP protocol ID used in the GRE 'proto' field */
107 #define PPTP_GRE_PROTO		0x880b
108 
109 /* Bits that must be set a certain way in all PPTP/GRE packets */
110 #define PPTP_INIT_VALUE		((0x2001 << 16) | PPTP_GRE_PROTO)
111 #define PPTP_INIT_MASK		0xef7fffff
112 
113 /* Min and max packet length */
114 #define PPTP_MAX_PAYLOAD	(0xffff - sizeof(struct greheader) - 8)
115 
116 /* All times are scaled by this (PPTP_TIME_SCALE time units = 1 sec.) */
117 #define PPTP_TIME_SCALE		1000			/* milliseconds */
118 typedef u_int64_t		pptptime_t;
119 
120 /* Acknowledgment timeout parameters and functions */
121 #define PPTP_XMIT_WIN		16			/* max xmit window */
122 #define PPTP_MIN_RTT		(PPTP_TIME_SCALE / 10)	/* 100 milliseconds */
123 #define PPTP_MIN_TIMEOUT	(PPTP_TIME_SCALE / 83)	/* 12 milliseconds */
124 #define PPTP_MAX_TIMEOUT	(10 * PPTP_TIME_SCALE)	/* 10 seconds */
125 
126 /* When we recieve a packet, we wait to see if there's an outgoing packet
127    we can piggy-back the ACK off of. These parameters determine the mimimum
128    and maxmimum length of time we're willing to wait in order to do that.
129    These have no effect unless "enableDelayedAck" is turned on. */
130 #define PPTP_MIN_ACK_DELAY	(PPTP_TIME_SCALE / 500)	/* 2 milliseconds */
131 #define PPTP_MAX_ACK_DELAY	(PPTP_TIME_SCALE / 2)	/* 500 milliseconds */
132 
133 /* See RFC 2637 section 4.4 */
134 #define PPTP_ACK_ALPHA(x)	((x) >> 3)	/* alpha = 0.125 */
135 #define PPTP_ACK_BETA(x)	((x) >> 2)	/* beta = 0.25 */
136 #define PPTP_ACK_CHI(x) 	((x) << 2)	/* chi = 4 */
137 #define PPTP_ACK_DELTA(x) 	((x) << 1)	/* delta = 2 */
138 
139 #define PPTP_SEQ_DIFF(x,y)	((int32_t)(x) - (int32_t)(y))
140 
141 /* We keep packet retransmit and acknowlegement state in this struct */
142 struct ng_pptpgre_ackp {
143 	int32_t			ato;		/* adaptive time-out value */
144 	int32_t			rtt;		/* round trip time estimate */
145 	int32_t			dev;		/* deviation estimate */
146 	u_int16_t		xmitWin;	/* size of xmit window */
147 	struct callout		sackTimer;	/* send ack timer */
148 	struct callout		rackTimer;	/* recv ack timer */
149 	node_p			*sackTimerPtr;	/* send ack timer pointer */
150 	node_p			*rackTimerPtr;	/* recv ack timer pointer */
151 	u_int32_t		winAck;		/* seq when xmitWin will grow */
152 	pptptime_t		timeSent[PPTP_XMIT_WIN];
153 #ifdef DEBUG_RAT
154 	pptptime_t		timerStart;	/* when rackTimer started */
155 	pptptime_t		timerLength;	/* rackTimer duration */
156 #endif
157 };
158 
159 /* Node private data */
160 struct ng_pptpgre_private {
161 	hook_p			upper;		/* hook to upper layers */
162 	hook_p			lower;		/* hook to lower layers */
163 	struct ng_pptpgre_conf	conf;		/* configuration info */
164 	struct ng_pptpgre_ackp	ackp;		/* packet transmit ack state */
165 	u_int32_t		recvSeq;	/* last seq # we rcv'd */
166 	u_int32_t		xmitSeq;	/* last seq # we sent */
167 	u_int32_t		recvAck;	/* last seq # peer ack'd */
168 	u_int32_t		xmitAck;	/* last seq # we ack'd */
169 	u_int			timers;		/* number of pending timers */
170 	struct timeval		startTime;	/* time node was created */
171 	struct ng_pptpgre_stats	stats;		/* node statistics */
172 };
173 typedef struct ng_pptpgre_private *priv_p;
174 
175 /* Netgraph node methods */
176 static ng_constructor_t	ng_pptpgre_constructor;
177 static ng_rcvmsg_t	ng_pptpgre_rcvmsg;
178 static ng_shutdown_t	ng_pptpgre_rmnode;
179 static ng_newhook_t	ng_pptpgre_newhook;
180 static ng_rcvdata_t	ng_pptpgre_rcvdata;
181 static ng_disconnect_t	ng_pptpgre_disconnect;
182 
183 /* Helper functions */
184 static int	ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta);
185 static int	ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta);
186 static void	ng_pptpgre_start_send_ack_timer(node_p node, int ackTimeout);
187 static void	ng_pptpgre_stop_send_ack_timer(node_p node);
188 static void	ng_pptpgre_start_recv_ack_timer(node_p node);
189 static void	ng_pptpgre_stop_recv_ack_timer(node_p node);
190 static void	ng_pptpgre_recv_ack_timeout(void *arg);
191 static void	ng_pptpgre_send_ack_timeout(void *arg);
192 static void	ng_pptpgre_reset(node_p node);
193 static pptptime_t ng_pptpgre_time(node_p node);
194 
195 /* Parse type for struct ng_pptpgre_conf */
196 static const struct ng_parse_struct_field ng_pptpgre_conf_type_fields[]
197 	= NG_PPTPGRE_CONF_TYPE_INFO;
198 static const struct ng_parse_type ng_pptpgre_conf_type = {
199 	&ng_parse_struct_type,
200 	&ng_pptpgre_conf_type_fields,
201 };
202 
203 /* Parse type for struct ng_pptpgre_stats */
204 static const struct ng_parse_struct_field ng_pptpgre_stats_type_fields[]
205 	= NG_PPTPGRE_STATS_TYPE_INFO;
206 static const struct ng_parse_type ng_pptp_stats_type = {
207 	&ng_parse_struct_type,
208 	&ng_pptpgre_stats_type_fields
209 };
210 
211 /* List of commands and how to convert arguments to/from ASCII */
212 static const struct ng_cmdlist ng_pptpgre_cmdlist[] = {
213 	{
214 	  NGM_PPTPGRE_COOKIE,
215 	  NGM_PPTPGRE_SET_CONFIG,
216 	  "setconfig",
217 	  &ng_pptpgre_conf_type,
218 	  NULL
219 	},
220 	{
221 	  NGM_PPTPGRE_COOKIE,
222 	  NGM_PPTPGRE_GET_CONFIG,
223 	  "getconfig",
224 	  NULL,
225 	  &ng_pptpgre_conf_type
226 	},
227 	{
228 	  NGM_PPTPGRE_COOKIE,
229 	  NGM_PPTPGRE_GET_STATS,
230 	  "getstats",
231 	  NULL,
232 	  &ng_pptp_stats_type
233 	},
234 	{
235 	  NGM_PPTPGRE_COOKIE,
236 	  NGM_PPTPGRE_CLR_STATS,
237 	  "clrstats",
238 	  NULL,
239 	  NULL
240 	},
241 	{
242 	  NGM_PPTPGRE_COOKIE,
243 	  NGM_PPTPGRE_GETCLR_STATS,
244 	  "getclrstats",
245 	  NULL,
246 	  &ng_pptp_stats_type
247 	},
248 	{ 0 }
249 };
250 
251 /* Node type descriptor */
252 static struct ng_type ng_pptpgre_typestruct = {
253 	NG_VERSION,
254 	NG_PPTPGRE_NODE_TYPE,
255 	NULL,
256 	ng_pptpgre_constructor,
257 	ng_pptpgre_rcvmsg,
258 	ng_pptpgre_rmnode,
259 	ng_pptpgre_newhook,
260 	NULL,
261 	NULL,
262 	ng_pptpgre_rcvdata,
263 	ng_pptpgre_rcvdata,
264 	ng_pptpgre_disconnect,
265 	ng_pptpgre_cmdlist
266 };
267 NETGRAPH_INIT(pptpgre, &ng_pptpgre_typestruct);
268 
269 #define ERROUT(x)	do { error = (x); goto done; } while (0)
270 
271 /************************************************************************
272 			NETGRAPH NODE STUFF
273  ************************************************************************/
274 
275 /*
276  * Node type constructor
277  */
278 static int
279 ng_pptpgre_constructor(node_p *nodep)
280 {
281 	priv_p priv;
282 	int error;
283 
284 	/* Allocate private structure */
285 	priv = kmalloc(sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO);
286 	if (priv == NULL)
287 		return (ENOMEM);
288 
289 	/* Call generic node constructor */
290 	if ((error = ng_make_node_common(&ng_pptpgre_typestruct, nodep))) {
291 		kfree(priv, M_NETGRAPH);
292 		return (error);
293 	}
294 	(*nodep)->private = priv;
295 
296 	/* Initialize state */
297 	callout_init(&priv->ackp.sackTimer);
298 	callout_init(&priv->ackp.rackTimer);
299 
300 	/* Done */
301 	return (0);
302 }
303 
304 /*
305  * Give our OK for a hook to be added.
306  */
307 static int
308 ng_pptpgre_newhook(node_p node, hook_p hook, const char *name)
309 {
310 	const priv_p priv = node->private;
311 	hook_p *hookPtr;
312 
313 	/* Check hook name */
314 	if (strcmp(name, NG_PPTPGRE_HOOK_UPPER) == 0)
315 		hookPtr = &priv->upper;
316 	else if (strcmp(name, NG_PPTPGRE_HOOK_LOWER) == 0)
317 		hookPtr = &priv->lower;
318 	else
319 		return (EINVAL);
320 
321 	/* See if already connected */
322 	if (*hookPtr != NULL)
323 		return (EISCONN);
324 
325 	/* OK */
326 	*hookPtr = hook;
327 	return (0);
328 }
329 
330 /*
331  * Receive a control message.
332  */
333 static int
334 ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
335 	      const char *raddr, struct ng_mesg **rptr)
336 {
337 	const priv_p priv = node->private;
338 	struct ng_mesg *resp = NULL;
339 	int error = 0;
340 
341 	switch (msg->header.typecookie) {
342 	case NGM_PPTPGRE_COOKIE:
343 		switch (msg->header.cmd) {
344 		case NGM_PPTPGRE_SET_CONFIG:
345 		    {
346 			struct ng_pptpgre_conf *const newConf =
347 				(struct ng_pptpgre_conf *) msg->data;
348 
349 			/* Check for invalid or illegal config */
350 			if (msg->header.arglen != sizeof(*newConf))
351 				ERROUT(EINVAL);
352 			ng_pptpgre_reset(node);		/* reset on configure */
353 			priv->conf = *newConf;
354 			break;
355 		    }
356 		case NGM_PPTPGRE_GET_CONFIG:
357 			NG_MKRESPONSE(resp, msg, sizeof(priv->conf), M_NOWAIT);
358 			if (resp == NULL)
359 				ERROUT(ENOMEM);
360 			bcopy(&priv->conf, resp->data, sizeof(priv->conf));
361 			break;
362 		case NGM_PPTPGRE_GET_STATS:
363 		case NGM_PPTPGRE_CLR_STATS:
364 		case NGM_PPTPGRE_GETCLR_STATS:
365 		    {
366 			if (msg->header.cmd != NGM_PPTPGRE_CLR_STATS) {
367 				NG_MKRESPONSE(resp, msg,
368 				    sizeof(priv->stats), M_NOWAIT);
369 				if (resp == NULL)
370 					ERROUT(ENOMEM);
371 				bcopy(&priv->stats,
372 				    resp->data, sizeof(priv->stats));
373 			}
374 			if (msg->header.cmd != NGM_PPTPGRE_GET_STATS)
375 				bzero(&priv->stats, sizeof(priv->stats));
376 			break;
377 		    }
378 		default:
379 			error = EINVAL;
380 			break;
381 		}
382 		break;
383 	default:
384 		error = EINVAL;
385 		break;
386 	}
387 	if (rptr)
388 		*rptr = resp;
389 	else if (resp)
390 		kfree(resp, M_NETGRAPH);
391 
392 done:
393 	kfree(msg, M_NETGRAPH);
394 	return (error);
395 }
396 
397 /*
398  * Receive incoming data on a hook.
399  */
400 static int
401 ng_pptpgre_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
402 {
403 	const node_p node = hook->node;
404 	const priv_p priv = node->private;
405 
406 	/* If not configured, reject */
407 	if (!priv->conf.enabled) {
408 		NG_FREE_DATA(m, meta);
409 		return (ENXIO);
410 	}
411 
412 	/* Treat as xmit or recv data */
413 	if (hook == priv->upper)
414 		return ng_pptpgre_xmit(node, m, meta);
415 	if (hook == priv->lower)
416 		return ng_pptpgre_recv(node, m, meta);
417 	panic("%s: weird hook", __func__);
418 }
419 
420 /*
421  * Destroy node
422  */
423 static int
424 ng_pptpgre_rmnode(node_p node)
425 {
426 	const priv_p priv = node->private;
427 
428 	/* Reset node */
429 	ng_pptpgre_reset(node);
430 
431 	/* Take down netgraph node */
432 	node->flags |= NG_INVALID;
433 	ng_cutlinks(node);
434 	ng_unname(node);
435 
436 	/* If no timers remain, free private info as well */
437 	if (priv->timers == 0) {
438 		kfree(priv, M_NETGRAPH);
439 		node->private = NULL;
440 	}
441 
442 	/* Done */
443 	ng_unref(node);
444 	return (0);
445 }
446 
447 /*
448  * Hook disconnection
449  */
450 static int
451 ng_pptpgre_disconnect(hook_p hook)
452 {
453 	const node_p node = hook->node;
454 	const priv_p priv = node->private;
455 
456 	/* Zero out hook pointer */
457 	if (hook == priv->upper)
458 		priv->upper = NULL;
459 	else if (hook == priv->lower)
460 		priv->lower = NULL;
461 	else
462 		panic("%s: unknown hook", __func__);
463 
464 	/* Go away if no longer connected to anything */
465 	if (node->numhooks == 0)
466 		ng_rmnode(node);
467 	return (0);
468 }
469 
470 /*************************************************************************
471 		    TRANSMIT AND RECEIVE FUNCTIONS
472 *************************************************************************/
473 
474 /*
475  * Transmit an outgoing frame, or just an ack if m is NULL.
476  */
477 static int
478 ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
479 {
480 	const priv_p priv = node->private;
481 	struct ng_pptpgre_ackp *const a = &priv->ackp;
482 	u_char buf[sizeof(struct greheader) + 2 * sizeof(u_int32_t)];
483 	struct greheader *const gre = (struct greheader *)buf;
484 	int grelen, error;
485 
486 	/* Check if there's data */
487 	if (m != NULL) {
488 
489 		/* Is our transmit window full? */
490 		if ((u_int32_t)PPTP_SEQ_DIFF(priv->xmitSeq, priv->recvAck)
491 		      >= a->xmitWin) {
492 			priv->stats.xmitDrops++;
493 			NG_FREE_DATA(m, meta);
494 			return (ENOBUFS);
495 		}
496 
497 		/* Sanity check frame length */
498 		if (m != NULL && m->m_pkthdr.len > PPTP_MAX_PAYLOAD) {
499 			priv->stats.xmitTooBig++;
500 			NG_FREE_DATA(m, meta);
501 			return (EMSGSIZE);
502 		}
503 	} else
504 		priv->stats.xmitLoneAcks++;
505 
506 	/* Build GRE header */
507 	((u_int32_t *)gre)[0] = htonl(PPTP_INIT_VALUE);
508 	gre->length = (m != NULL) ? htons((u_short)m->m_pkthdr.len) : 0;
509 	gre->cid = htons(priv->conf.peerCid);
510 
511 	/* Include sequence number if packet contains any data */
512 	if (m != NULL) {
513 		gre->hasSeq = 1;
514 		a->timeSent[priv->xmitSeq - priv->recvAck]
515 		    = ng_pptpgre_time(node);
516 		priv->xmitSeq++;
517 		gre->data[0] = htonl(priv->xmitSeq);
518 	}
519 
520 	/* Include acknowledgement (and stop send ack timer) if needed */
521 	if (priv->conf.enableAlwaysAck || priv->xmitAck != priv->recvSeq) {
522 		gre->hasAck = 1;
523 		gre->data[gre->hasSeq] = htonl(priv->recvSeq);
524 		priv->xmitAck = priv->recvSeq;
525 		ng_pptpgre_stop_send_ack_timer(node);
526 	}
527 
528 	/* Prepend GRE header to outgoing frame */
529 	grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck);
530 	if (m == NULL) {
531 		MGETHDR(m, MB_DONTWAIT, MT_DATA);
532 		if (m == NULL) {
533 			priv->stats.memoryFailures++;
534 			NG_FREE_META(meta);
535 			return (ENOBUFS);
536 		}
537 		m->m_len = m->m_pkthdr.len = grelen;
538 		m->m_pkthdr.rcvif = NULL;
539 	} else {
540 		M_PREPEND(m, grelen, MB_DONTWAIT);
541 		if (m == NULL || (m->m_len < grelen
542 		    && (m = m_pullup(m, grelen)) == NULL)) {
543 			priv->stats.memoryFailures++;
544 			NG_FREE_META(meta);
545 			return (ENOBUFS);
546 		}
547 	}
548 	bcopy(gre, mtod(m, u_char *), grelen);
549 
550 	/* Update stats */
551 	priv->stats.xmitPackets++;
552 	priv->stats.xmitOctets += m->m_pkthdr.len;
553 
554 	/* Deliver packet */
555 	NG_SEND_DATA(error, priv->lower, m, meta);
556 
557 	/* Start receive ACK timer if data was sent and not already running */
558 	if (error == 0 && gre->hasSeq && priv->xmitSeq == priv->recvAck + 1)
559 		ng_pptpgre_start_recv_ack_timer(node);
560 	return (error);
561 }
562 
563 /*
564  * Handle an incoming packet.  The packet includes the IP header.
565  */
566 static int
567 ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
568 {
569 	const priv_p priv = node->private;
570 	int iphlen, grelen, extralen;
571 	const struct greheader *gre;
572 	const struct ip *ip;
573 	int error = 0;
574 
575 	/* Update stats */
576 	priv->stats.recvPackets++;
577 	priv->stats.recvOctets += m->m_pkthdr.len;
578 
579 	/* Sanity check packet length */
580 	if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) {
581 		priv->stats.recvRunts++;
582 bad:
583 		NG_FREE_DATA(m, meta);
584 		return (EINVAL);
585 	}
586 
587 	/* Safely pull up the complete IP+GRE headers */
588 	if (m->m_len < sizeof(*ip) + sizeof(*gre)
589 	    && (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
590 		priv->stats.memoryFailures++;
591 		NG_FREE_META(meta);
592 		return (ENOBUFS);
593 	}
594 	ip = mtod(m, const struct ip *);
595 	iphlen = ip->ip_hl << 2;
596 	if (m->m_len < iphlen + sizeof(*gre)) {
597 		if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) {
598 			priv->stats.memoryFailures++;
599 			NG_FREE_META(meta);
600 			return (ENOBUFS);
601 		}
602 		ip = mtod(m, const struct ip *);
603 	}
604 	gre = (const struct greheader *)((const u_char *)ip + iphlen);
605 	grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck);
606 	if (m->m_pkthdr.len < iphlen + grelen) {
607 		priv->stats.recvRunts++;
608 		goto bad;
609 	}
610 	if (m->m_len < iphlen + grelen) {
611 		if ((m = m_pullup(m, iphlen + grelen)) == NULL) {
612 			priv->stats.memoryFailures++;
613 			NG_FREE_META(meta);
614 			return (ENOBUFS);
615 		}
616 		ip = mtod(m, const struct ip *);
617 		gre = (const struct greheader *)((const u_char *)ip + iphlen);
618 	}
619 
620 	/* Sanity check packet length and GRE header bits */
621 	extralen = m->m_pkthdr.len
622 	    - (iphlen + grelen + gre->hasSeq * (u_int16_t)ntohs(gre->length));
623 	if (extralen < 0) {
624 		priv->stats.recvBadGRE++;
625 		goto bad;
626 	}
627 	if ((ntohl(*((const u_int32_t *)gre)) & PPTP_INIT_MASK)
628 	    != PPTP_INIT_VALUE) {
629 		priv->stats.recvBadGRE++;
630 		goto bad;
631 	}
632 	if (ntohs(gre->cid) != priv->conf.cid) {
633 		priv->stats.recvBadCID++;
634 		goto bad;
635 	}
636 
637 	/* Look for peer ack */
638 	if (gre->hasAck) {
639 		struct ng_pptpgre_ackp *const a = &priv->ackp;
640 		const u_int32_t	ack = ntohl(gre->data[gre->hasSeq]);
641 		const int index = ack - priv->recvAck - 1;
642 		long sample;
643 		long diff;
644 
645 		/* Sanity check ack value */
646 		if (PPTP_SEQ_DIFF(ack, priv->xmitSeq) > 0) {
647 			priv->stats.recvBadAcks++;
648 			goto badAck;		/* we never sent it! */
649 		}
650 		if (PPTP_SEQ_DIFF(ack, priv->recvAck) <= 0)
651 			goto badAck;		/* ack already timed out */
652 		priv->recvAck = ack;
653 
654 		/* Update adaptive timeout stuff */
655 		sample = ng_pptpgre_time(node) - a->timeSent[index];
656 		diff = sample - a->rtt;
657 		a->rtt += PPTP_ACK_ALPHA(diff);
658 		if (diff < 0)
659 			diff = -diff;
660 		a->dev += PPTP_ACK_BETA(diff - a->dev);
661 		a->ato = a->rtt + PPTP_ACK_CHI(a->dev);
662 		if (a->ato > PPTP_MAX_TIMEOUT)
663 			a->ato = PPTP_MAX_TIMEOUT;
664 		if (a->ato < PPTP_MIN_TIMEOUT)
665 			a->ato = PPTP_MIN_TIMEOUT;
666 
667 		/* Shift packet transmit times in our transmit window */
668 		ovbcopy(a->timeSent + index + 1, a->timeSent,
669 		    sizeof(*a->timeSent) * (PPTP_XMIT_WIN - (index + 1)));
670 
671 		/* If we sent an entire window, increase window size by one */
672 		if (PPTP_SEQ_DIFF(ack, a->winAck) >= 0
673 		    && a->xmitWin < PPTP_XMIT_WIN) {
674 			a->xmitWin++;
675 			a->winAck = ack + a->xmitWin;
676 		}
677 
678 		/* Stop/(re)start receive ACK timer as necessary */
679 		ng_pptpgre_stop_recv_ack_timer(node);
680 		if (priv->recvAck != priv->xmitSeq)
681 			ng_pptpgre_start_recv_ack_timer(node);
682 	}
683 badAck:
684 
685 	/* See if frame contains any data */
686 	if (gre->hasSeq) {
687 		struct ng_pptpgre_ackp *const a = &priv->ackp;
688 		const u_int32_t seq = ntohl(gre->data[0]);
689 
690 		/* Sanity check sequence number */
691 		if (PPTP_SEQ_DIFF(seq, priv->recvSeq) <= 0) {
692 			if (seq == priv->recvSeq)
693 				priv->stats.recvDuplicates++;
694 			else
695 				priv->stats.recvOutOfOrder++;
696 			goto bad;		/* out-of-order or dup */
697 		}
698 		priv->recvSeq = seq;
699 
700 		/* We need to acknowledge this packet; do it soon... */
701 		if (a->sackTimerPtr == NULL) {
702 			int maxWait;
703 
704 			/* Take 1/4 of the estimated round trip time */
705 			maxWait = (a->rtt >> 2);
706 
707 			/* If delayed ACK is disabled, send it now */
708 			if (!priv->conf.enableDelayedAck)	/* ack now */
709 				ng_pptpgre_xmit(node, NULL, NULL);
710 			else {					/* ack later */
711 				if (maxWait < PPTP_MIN_ACK_DELAY)
712 					maxWait = PPTP_MIN_ACK_DELAY;
713 				if (maxWait > PPTP_MAX_ACK_DELAY)
714 					maxWait = PPTP_MAX_ACK_DELAY;
715 				ng_pptpgre_start_send_ack_timer(node, maxWait);
716 			}
717 		}
718 
719 		/* Trim mbuf down to internal payload */
720 		m_adj(m, iphlen + grelen);
721 		if (extralen > 0)
722 			m_adj(m, -extralen);
723 
724 		/* Deliver frame to upper layers */
725 		NG_SEND_DATA(error, priv->upper, m, meta);
726 	} else {
727 		priv->stats.recvLoneAcks++;
728 		NG_FREE_DATA(m, meta);		/* no data to deliver */
729 	}
730 	return (error);
731 }
732 
733 /*************************************************************************
734 		    TIMER RELATED FUNCTIONS
735 *************************************************************************/
736 
737 /*
738  * Start a timer for the peer's acknowledging our oldest unacknowledged
739  * sequence number.  If we get an ack for this sequence number before
740  * the timer goes off, we cancel the timer.  Resets currently running
741  * recv ack timer, if any.
742  */
743 static void
744 ng_pptpgre_start_recv_ack_timer(node_p node)
745 {
746 	const priv_p priv = node->private;
747 	struct ng_pptpgre_ackp *const a = &priv->ackp;
748 	int remain, ticks;
749 
750 	/* Compute how long until oldest unack'd packet times out,
751 	   and reset the timer to that time. */
752 	KASSERT(a->rackTimerPtr == NULL, ("%s: rackTimer", __func__));
753 	remain = (a->timeSent[0] + a->ato) - ng_pptpgre_time(node);
754 	if (remain < 0)
755 		remain = 0;
756 #ifdef DEBUG_RAT
757 	a->timerLength = remain;
758 	a->timerStart = ng_pptpgre_time(node);
759 #endif
760 
761 	/* Start new timer */
762 	a->rackTimerPtr = kmalloc(sizeof(node_p), M_NETGRAPH, M_NOWAIT);
763 	if (a->rackTimerPtr == NULL) {
764 		priv->stats.memoryFailures++;
765 		return;			/* XXX potential hang here */
766 	}
767 	*a->rackTimerPtr = node;	/* ensures the correct timeout event */
768 	node->refs++;
769 	priv->timers++;
770 
771 	/* Be conservative: timeout can happen up to 1 tick early */
772 	ticks = (((remain * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE) + 1;
773 	callout_reset(&a->rackTimer, ticks,
774 	    ng_pptpgre_recv_ack_timeout, a->rackTimerPtr);
775 }
776 
777 /*
778  * Stop receive ack timer.
779  */
780 static void
781 ng_pptpgre_stop_recv_ack_timer(node_p node)
782 {
783 	const priv_p priv = node->private;
784 	struct ng_pptpgre_ackp *const a = &priv->ackp;
785 
786 	if (callout_stop(&a->rackTimer)) {
787 		kfree(a->rackTimerPtr, M_NETGRAPH);
788 		priv->timers--;
789 		ng_unref(node);
790 	}
791 	a->rackTimerPtr = NULL;
792 }
793 
794 /*
795  * The peer has failed to acknowledge the oldest unacknowledged sequence
796  * number within the time allotted.  Update our adaptive timeout parameters
797  * and reset/restart the recv ack timer.
798  */
799 static void
800 ng_pptpgre_recv_ack_timeout(void *arg)
801 {
802 	const node_p node = *((node_p *)arg);
803 	const priv_p priv = node->private;
804 	struct ng_pptpgre_ackp *const a = &priv->ackp;
805 
806 	crit_enter();
807 	/* This complicated stuff is needed to avoid race conditions */
808 	kfree(arg, M_NETGRAPH);
809 	KASSERT(node->refs > 0, ("%s: no refs", __func__));
810 	KASSERT(priv != NULL, ("%s: priv=NULL", __func__));
811 	priv->timers--;
812 	if ((node->flags & NG_INVALID) != 0) {	/* shutdown race condition */
813 		if (priv->timers == 0) {
814 			kfree(priv, M_NETGRAPH);
815 			node->private = NULL;
816 		}
817 		ng_unref(node);
818 		crit_exit();
819 		return;
820 	}
821 	if (arg != a->rackTimerPtr) {	/* timer stopped race condition */
822 		ng_unref(node);
823 		crit_exit();
824 		return;
825 	}
826 	a->rackTimerPtr = NULL;
827 
828 	/* Update adaptive timeout stuff */
829 	priv->stats.recvAckTimeouts++;
830 	a->rtt = PPTP_ACK_DELTA(a->rtt);
831 	a->ato = a->rtt + PPTP_ACK_CHI(a->dev);
832 	if (a->ato > PPTP_MAX_TIMEOUT)
833 		a->ato = PPTP_MAX_TIMEOUT;
834 	if (a->ato < PPTP_MIN_TIMEOUT)
835 		a->ato = PPTP_MIN_TIMEOUT;
836 
837 #ifdef DEBUG_RAT
838     log(LOG_DEBUG,
839 	"RAT now=%d seq=0x%x sent=%d tstart=%d tlen=%d ato=%d\n",
840 	(int)ng_pptpgre_time(node), priv->recvAck + 1,
841 	(int)a->timeSent[0], (int)a->timerStart, (int)a->timerLength, a->ato);
842 #endif
843 
844 	/* Reset ack and sliding window */
845 	priv->recvAck = priv->xmitSeq;		/* pretend we got the ack */
846 	a->xmitWin = (a->xmitWin + 1) / 2;	/* shrink transmit window */
847 	a->winAck = priv->recvAck + a->xmitWin;	/* reset win expand time */
848 	ng_unref(node);
849 	crit_exit();
850 }
851 
852 /*
853  * Start the send ack timer. This assumes the timer is not
854  * already running.
855  */
856 static void
857 ng_pptpgre_start_send_ack_timer(node_p node, int ackTimeout)
858 {
859 	const priv_p priv = node->private;
860 	struct ng_pptpgre_ackp *const a = &priv->ackp;
861 	int ticks;
862 
863 	/* Start new timer */
864 	KASSERT(a->sackTimerPtr == NULL, ("%s: sackTimer", __func__));
865 	a->sackTimerPtr = kmalloc(sizeof(node_p), M_NETGRAPH, M_NOWAIT);
866 	if (a->sackTimerPtr == NULL) {
867 		priv->stats.memoryFailures++;
868 		return;			/* XXX potential hang here */
869 	}
870 	*a->sackTimerPtr = node;	/* ensures the correct timeout event */
871 	node->refs++;
872 	priv->timers++;
873 
874 	/* Be conservative: timeout can happen up to 1 tick early */
875 	ticks = (((ackTimeout * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE);
876 	callout_reset(&a->sackTimer, ticks,
877 	    ng_pptpgre_send_ack_timeout, a->sackTimerPtr);
878 }
879 
880 /*
881  * Stop send ack timer.
882  */
883 static void
884 ng_pptpgre_stop_send_ack_timer(node_p node)
885 {
886 	const priv_p priv = node->private;
887 	struct ng_pptpgre_ackp *const a = &priv->ackp;
888 
889 	if (callout_stop(&a->sackTimer)) {
890 		kfree(a->sackTimerPtr, M_NETGRAPH);
891 		priv->timers--;
892 		ng_unref(node);
893 	}
894 	a->sackTimerPtr = NULL;
895 }
896 
897 /*
898  * We've waited as long as we're willing to wait before sending an
899  * acknowledgement to the peer for received frames. We had hoped to
900  * be able to piggy back our acknowledgement on an outgoing data frame,
901  * but apparently there haven't been any since. So send the ack now.
902  */
903 static void
904 ng_pptpgre_send_ack_timeout(void *arg)
905 {
906 	const node_p node = *((node_p *)arg);
907 	const priv_p priv = node->private;
908 	struct ng_pptpgre_ackp *const a = &priv->ackp;
909 
910 	crit_enter();
911 	/* This complicated stuff is needed to avoid race conditions */
912 	kfree(arg, M_NETGRAPH);
913 	KASSERT(node->refs > 0, ("%s: no refs", __func__));
914 	KASSERT(priv != NULL, ("%s: priv=NULL", __func__));
915 	priv->timers--;
916 	if ((node->flags & NG_INVALID) != 0) {	/* shutdown race condition */
917 		if (priv->timers == 0) {
918 			kfree(priv, M_NETGRAPH);
919 			node->private = NULL;
920 		}
921 		ng_unref(node);
922 		crit_exit();
923 		return;
924 	}
925 	if (a->sackTimerPtr != arg) {	/* timer stopped race condition */
926 		ng_unref(node);
927 		crit_exit();
928 		return;
929 	}
930 	a->sackTimerPtr = NULL;
931 
932 	/* Send a frame with an ack but no payload */
933   	ng_pptpgre_xmit(node, NULL, NULL);
934 	ng_unref(node);
935 	crit_exit();
936 }
937 
938 /*************************************************************************
939 		    MISC FUNCTIONS
940 *************************************************************************/
941 
942 /*
943  * Reset state
944  */
945 static void
946 ng_pptpgre_reset(node_p node)
947 {
948 	const priv_p priv = node->private;
949 	struct ng_pptpgre_ackp *const a = &priv->ackp;
950 
951 	/* Reset adaptive timeout state */
952 	a->ato = PPTP_MAX_TIMEOUT;
953 	a->rtt = priv->conf.peerPpd * PPTP_TIME_SCALE / 10;  /* ppd in 10ths */
954 	if (a->rtt < PPTP_MIN_RTT)
955 		a->rtt = PPTP_MIN_RTT;
956 	a->dev = 0;
957 	a->xmitWin = (priv->conf.recvWin + 1) / 2;
958 	if (a->xmitWin < 2)		/* often the first packet is lost */
959 		a->xmitWin = 2;		/*   because the peer isn't ready */
960 	if (a->xmitWin > PPTP_XMIT_WIN)
961 		a->xmitWin = PPTP_XMIT_WIN;
962 	a->winAck = a->xmitWin;
963 
964 	/* Reset sequence numbers */
965 	priv->recvSeq = ~0;
966 	priv->recvAck = ~0;
967 	priv->xmitSeq = ~0;
968 	priv->xmitAck = ~0;
969 
970 	/* Reset start time */
971 	getmicrouptime(&priv->startTime);
972 
973 	/* Reset stats */
974 	bzero(&priv->stats, sizeof(priv->stats));
975 
976 	/* Stop timers */
977 	ng_pptpgre_stop_send_ack_timer(node);
978 	ng_pptpgre_stop_recv_ack_timer(node);
979 }
980 
981 /*
982  * Return the current time scaled & translated to our internally used format.
983  */
984 static pptptime_t
985 ng_pptpgre_time(node_p node)
986 {
987 	const priv_p priv = node->private;
988 	struct timeval tv;
989 	pptptime_t t;
990 
991 	microuptime(&tv);
992 	if (tv.tv_sec < priv->startTime.tv_sec
993 	    || (tv.tv_sec == priv->startTime.tv_sec
994 	      && tv.tv_usec < priv->startTime.tv_usec))
995 		return (0);
996 	timevalsub(&tv, &priv->startTime);
997 	t = (pptptime_t)tv.tv_sec * PPTP_TIME_SCALE;
998 	t += (pptptime_t)tv.tv_usec / (1000000 / PPTP_TIME_SCALE);
999 	return(t);
1000 }
1001 
1002