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