xref: /dragonfly/sys/netgraph/pptpgre/ng_pptpgre.c (revision c03f08f3)
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.7 2005/06/02 22:11:46 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);
287 	if (priv == NULL)
288 		return (ENOMEM);
289 	bzero(priv, sizeof(*priv));
290 
291 	/* Call generic node constructor */
292 	if ((error = ng_make_node_common(&ng_pptpgre_typestruct, nodep))) {
293 		FREE(priv, M_NETGRAPH);
294 		return (error);
295 	}
296 	(*nodep)->private = priv;
297 
298 	/* Initialize state */
299 	callout_init(&priv->ackp.sackTimer);
300 	callout_init(&priv->ackp.rackTimer);
301 
302 	/* Done */
303 	return (0);
304 }
305 
306 /*
307  * Give our OK for a hook to be added.
308  */
309 static int
310 ng_pptpgre_newhook(node_p node, hook_p hook, const char *name)
311 {
312 	const priv_p priv = node->private;
313 	hook_p *hookPtr;
314 
315 	/* Check hook name */
316 	if (strcmp(name, NG_PPTPGRE_HOOK_UPPER) == 0)
317 		hookPtr = &priv->upper;
318 	else if (strcmp(name, NG_PPTPGRE_HOOK_LOWER) == 0)
319 		hookPtr = &priv->lower;
320 	else
321 		return (EINVAL);
322 
323 	/* See if already connected */
324 	if (*hookPtr != NULL)
325 		return (EISCONN);
326 
327 	/* OK */
328 	*hookPtr = hook;
329 	return (0);
330 }
331 
332 /*
333  * Receive a control message.
334  */
335 static int
336 ng_pptpgre_rcvmsg(node_p node, struct ng_mesg *msg,
337 	      const char *raddr, struct ng_mesg **rptr)
338 {
339 	const priv_p priv = node->private;
340 	struct ng_mesg *resp = NULL;
341 	int error = 0;
342 
343 	switch (msg->header.typecookie) {
344 	case NGM_PPTPGRE_COOKIE:
345 		switch (msg->header.cmd) {
346 		case NGM_PPTPGRE_SET_CONFIG:
347 		    {
348 			struct ng_pptpgre_conf *const newConf =
349 				(struct ng_pptpgre_conf *) msg->data;
350 
351 			/* Check for invalid or illegal config */
352 			if (msg->header.arglen != sizeof(*newConf))
353 				ERROUT(EINVAL);
354 			ng_pptpgre_reset(node);		/* reset on configure */
355 			priv->conf = *newConf;
356 			break;
357 		    }
358 		case NGM_PPTPGRE_GET_CONFIG:
359 			NG_MKRESPONSE(resp, msg, sizeof(priv->conf), M_NOWAIT);
360 			if (resp == NULL)
361 				ERROUT(ENOMEM);
362 			bcopy(&priv->conf, resp->data, sizeof(priv->conf));
363 			break;
364 		case NGM_PPTPGRE_GET_STATS:
365 		case NGM_PPTPGRE_CLR_STATS:
366 		case NGM_PPTPGRE_GETCLR_STATS:
367 		    {
368 			if (msg->header.cmd != NGM_PPTPGRE_CLR_STATS) {
369 				NG_MKRESPONSE(resp, msg,
370 				    sizeof(priv->stats), M_NOWAIT);
371 				if (resp == NULL)
372 					ERROUT(ENOMEM);
373 				bcopy(&priv->stats,
374 				    resp->data, sizeof(priv->stats));
375 			}
376 			if (msg->header.cmd != NGM_PPTPGRE_GET_STATS)
377 				bzero(&priv->stats, sizeof(priv->stats));
378 			break;
379 		    }
380 		default:
381 			error = EINVAL;
382 			break;
383 		}
384 		break;
385 	default:
386 		error = EINVAL;
387 		break;
388 	}
389 	if (rptr)
390 		*rptr = resp;
391 	else if (resp)
392 		FREE(resp, M_NETGRAPH);
393 
394 done:
395 	FREE(msg, M_NETGRAPH);
396 	return (error);
397 }
398 
399 /*
400  * Receive incoming data on a hook.
401  */
402 static int
403 ng_pptpgre_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
404 {
405 	const node_p node = hook->node;
406 	const priv_p priv = node->private;
407 
408 	/* If not configured, reject */
409 	if (!priv->conf.enabled) {
410 		NG_FREE_DATA(m, meta);
411 		return (ENXIO);
412 	}
413 
414 	/* Treat as xmit or recv data */
415 	if (hook == priv->upper)
416 		return ng_pptpgre_xmit(node, m, meta);
417 	if (hook == priv->lower)
418 		return ng_pptpgre_recv(node, m, meta);
419 	panic("%s: weird hook", __func__);
420 }
421 
422 /*
423  * Destroy node
424  */
425 static int
426 ng_pptpgre_rmnode(node_p node)
427 {
428 	const priv_p priv = node->private;
429 
430 	/* Reset node */
431 	ng_pptpgre_reset(node);
432 
433 	/* Take down netgraph node */
434 	node->flags |= NG_INVALID;
435 	ng_cutlinks(node);
436 	ng_unname(node);
437 
438 	/* If no timers remain, free private info as well */
439 	if (priv->timers == 0) {
440 		FREE(priv, M_NETGRAPH);
441 		node->private = NULL;
442 	}
443 
444 	/* Done */
445 	ng_unref(node);
446 	return (0);
447 }
448 
449 /*
450  * Hook disconnection
451  */
452 static int
453 ng_pptpgre_disconnect(hook_p hook)
454 {
455 	const node_p node = hook->node;
456 	const priv_p priv = node->private;
457 
458 	/* Zero out hook pointer */
459 	if (hook == priv->upper)
460 		priv->upper = NULL;
461 	else if (hook == priv->lower)
462 		priv->lower = NULL;
463 	else
464 		panic("%s: unknown hook", __func__);
465 
466 	/* Go away if no longer connected to anything */
467 	if (node->numhooks == 0)
468 		ng_rmnode(node);
469 	return (0);
470 }
471 
472 /*************************************************************************
473 		    TRANSMIT AND RECEIVE FUNCTIONS
474 *************************************************************************/
475 
476 /*
477  * Transmit an outgoing frame, or just an ack if m is NULL.
478  */
479 static int
480 ng_pptpgre_xmit(node_p node, struct mbuf *m, meta_p meta)
481 {
482 	const priv_p priv = node->private;
483 	struct ng_pptpgre_ackp *const a = &priv->ackp;
484 	u_char buf[sizeof(struct greheader) + 2 * sizeof(u_int32_t)];
485 	struct greheader *const gre = (struct greheader *)buf;
486 	int grelen, error;
487 
488 	/* Check if there's data */
489 	if (m != NULL) {
490 
491 		/* Is our transmit window full? */
492 		if ((u_int32_t)PPTP_SEQ_DIFF(priv->xmitSeq, priv->recvAck)
493 		      >= a->xmitWin) {
494 			priv->stats.xmitDrops++;
495 			NG_FREE_DATA(m, meta);
496 			return (ENOBUFS);
497 		}
498 
499 		/* Sanity check frame length */
500 		if (m != NULL && m->m_pkthdr.len > PPTP_MAX_PAYLOAD) {
501 			priv->stats.xmitTooBig++;
502 			NG_FREE_DATA(m, meta);
503 			return (EMSGSIZE);
504 		}
505 	} else
506 		priv->stats.xmitLoneAcks++;
507 
508 	/* Build GRE header */
509 	((u_int32_t *)gre)[0] = htonl(PPTP_INIT_VALUE);
510 	gre->length = (m != NULL) ? htons((u_short)m->m_pkthdr.len) : 0;
511 	gre->cid = htons(priv->conf.peerCid);
512 
513 	/* Include sequence number if packet contains any data */
514 	if (m != NULL) {
515 		gre->hasSeq = 1;
516 		a->timeSent[priv->xmitSeq - priv->recvAck]
517 		    = ng_pptpgre_time(node);
518 		priv->xmitSeq++;
519 		gre->data[0] = htonl(priv->xmitSeq);
520 	}
521 
522 	/* Include acknowledgement (and stop send ack timer) if needed */
523 	if (priv->conf.enableAlwaysAck || priv->xmitAck != priv->recvSeq) {
524 		gre->hasAck = 1;
525 		gre->data[gre->hasSeq] = htonl(priv->recvSeq);
526 		priv->xmitAck = priv->recvSeq;
527 		ng_pptpgre_stop_send_ack_timer(node);
528 	}
529 
530 	/* Prepend GRE header to outgoing frame */
531 	grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck);
532 	if (m == NULL) {
533 		MGETHDR(m, MB_DONTWAIT, MT_DATA);
534 		if (m == NULL) {
535 			priv->stats.memoryFailures++;
536 			NG_FREE_META(meta);
537 			return (ENOBUFS);
538 		}
539 		m->m_len = m->m_pkthdr.len = grelen;
540 		m->m_pkthdr.rcvif = NULL;
541 	} else {
542 		M_PREPEND(m, grelen, MB_DONTWAIT);
543 		if (m == NULL || (m->m_len < grelen
544 		    && (m = m_pullup(m, grelen)) == NULL)) {
545 			priv->stats.memoryFailures++;
546 			NG_FREE_META(meta);
547 			return (ENOBUFS);
548 		}
549 	}
550 	bcopy(gre, mtod(m, u_char *), grelen);
551 
552 	/* Update stats */
553 	priv->stats.xmitPackets++;
554 	priv->stats.xmitOctets += m->m_pkthdr.len;
555 
556 	/* Deliver packet */
557 	NG_SEND_DATA(error, priv->lower, m, meta);
558 
559 	/* Start receive ACK timer if data was sent and not already running */
560 	if (error == 0 && gre->hasSeq && priv->xmitSeq == priv->recvAck + 1)
561 		ng_pptpgre_start_recv_ack_timer(node);
562 	return (error);
563 }
564 
565 /*
566  * Handle an incoming packet.  The packet includes the IP header.
567  */
568 static int
569 ng_pptpgre_recv(node_p node, struct mbuf *m, meta_p meta)
570 {
571 	const priv_p priv = node->private;
572 	int iphlen, grelen, extralen;
573 	const struct greheader *gre;
574 	const struct ip *ip;
575 	int error = 0;
576 
577 	/* Update stats */
578 	priv->stats.recvPackets++;
579 	priv->stats.recvOctets += m->m_pkthdr.len;
580 
581 	/* Sanity check packet length */
582 	if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) {
583 		priv->stats.recvRunts++;
584 bad:
585 		NG_FREE_DATA(m, meta);
586 		return (EINVAL);
587 	}
588 
589 	/* Safely pull up the complete IP+GRE headers */
590 	if (m->m_len < sizeof(*ip) + sizeof(*gre)
591 	    && (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) {
592 		priv->stats.memoryFailures++;
593 		NG_FREE_META(meta);
594 		return (ENOBUFS);
595 	}
596 	ip = mtod(m, const struct ip *);
597 	iphlen = ip->ip_hl << 2;
598 	if (m->m_len < iphlen + sizeof(*gre)) {
599 		if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) {
600 			priv->stats.memoryFailures++;
601 			NG_FREE_META(meta);
602 			return (ENOBUFS);
603 		}
604 		ip = mtod(m, const struct ip *);
605 	}
606 	gre = (const struct greheader *)((const u_char *)ip + iphlen);
607 	grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck);
608 	if (m->m_pkthdr.len < iphlen + grelen) {
609 		priv->stats.recvRunts++;
610 		goto bad;
611 	}
612 	if (m->m_len < iphlen + grelen) {
613 		if ((m = m_pullup(m, iphlen + grelen)) == NULL) {
614 			priv->stats.memoryFailures++;
615 			NG_FREE_META(meta);
616 			return (ENOBUFS);
617 		}
618 		ip = mtod(m, const struct ip *);
619 		gre = (const struct greheader *)((const u_char *)ip + iphlen);
620 	}
621 
622 	/* Sanity check packet length and GRE header bits */
623 	extralen = m->m_pkthdr.len
624 	    - (iphlen + grelen + gre->hasSeq * (u_int16_t)ntohs(gre->length));
625 	if (extralen < 0) {
626 		priv->stats.recvBadGRE++;
627 		goto bad;
628 	}
629 	if ((ntohl(*((const u_int32_t *)gre)) & PPTP_INIT_MASK)
630 	    != PPTP_INIT_VALUE) {
631 		priv->stats.recvBadGRE++;
632 		goto bad;
633 	}
634 	if (ntohs(gre->cid) != priv->conf.cid) {
635 		priv->stats.recvBadCID++;
636 		goto bad;
637 	}
638 
639 	/* Look for peer ack */
640 	if (gre->hasAck) {
641 		struct ng_pptpgre_ackp *const a = &priv->ackp;
642 		const u_int32_t	ack = ntohl(gre->data[gre->hasSeq]);
643 		const int index = ack - priv->recvAck - 1;
644 		long sample;
645 		long diff;
646 
647 		/* Sanity check ack value */
648 		if (PPTP_SEQ_DIFF(ack, priv->xmitSeq) > 0) {
649 			priv->stats.recvBadAcks++;
650 			goto badAck;		/* we never sent it! */
651 		}
652 		if (PPTP_SEQ_DIFF(ack, priv->recvAck) <= 0)
653 			goto badAck;		/* ack already timed out */
654 		priv->recvAck = ack;
655 
656 		/* Update adaptive timeout stuff */
657 		sample = ng_pptpgre_time(node) - a->timeSent[index];
658 		diff = sample - a->rtt;
659 		a->rtt += PPTP_ACK_ALPHA(diff);
660 		if (diff < 0)
661 			diff = -diff;
662 		a->dev += PPTP_ACK_BETA(diff - a->dev);
663 		a->ato = a->rtt + PPTP_ACK_CHI(a->dev);
664 		if (a->ato > PPTP_MAX_TIMEOUT)
665 			a->ato = PPTP_MAX_TIMEOUT;
666 		if (a->ato < PPTP_MIN_TIMEOUT)
667 			a->ato = PPTP_MIN_TIMEOUT;
668 
669 		/* Shift packet transmit times in our transmit window */
670 		ovbcopy(a->timeSent + index + 1, a->timeSent,
671 		    sizeof(*a->timeSent) * (PPTP_XMIT_WIN - (index + 1)));
672 
673 		/* If we sent an entire window, increase window size by one */
674 		if (PPTP_SEQ_DIFF(ack, a->winAck) >= 0
675 		    && a->xmitWin < PPTP_XMIT_WIN) {
676 			a->xmitWin++;
677 			a->winAck = ack + a->xmitWin;
678 		}
679 
680 		/* Stop/(re)start receive ACK timer as necessary */
681 		ng_pptpgre_stop_recv_ack_timer(node);
682 		if (priv->recvAck != priv->xmitSeq)
683 			ng_pptpgre_start_recv_ack_timer(node);
684 	}
685 badAck:
686 
687 	/* See if frame contains any data */
688 	if (gre->hasSeq) {
689 		struct ng_pptpgre_ackp *const a = &priv->ackp;
690 		const u_int32_t seq = ntohl(gre->data[0]);
691 
692 		/* Sanity check sequence number */
693 		if (PPTP_SEQ_DIFF(seq, priv->recvSeq) <= 0) {
694 			if (seq == priv->recvSeq)
695 				priv->stats.recvDuplicates++;
696 			else
697 				priv->stats.recvOutOfOrder++;
698 			goto bad;		/* out-of-order or dup */
699 		}
700 		priv->recvSeq = seq;
701 
702 		/* We need to acknowledge this packet; do it soon... */
703 		if (a->sackTimerPtr == NULL) {
704 			int maxWait;
705 
706 			/* Take 1/4 of the estimated round trip time */
707 			maxWait = (a->rtt >> 2);
708 
709 			/* If delayed ACK is disabled, send it now */
710 			if (!priv->conf.enableDelayedAck)	/* ack now */
711 				ng_pptpgre_xmit(node, NULL, NULL);
712 			else {					/* ack later */
713 				if (maxWait < PPTP_MIN_ACK_DELAY)
714 					maxWait = PPTP_MIN_ACK_DELAY;
715 				if (maxWait > PPTP_MAX_ACK_DELAY)
716 					maxWait = PPTP_MAX_ACK_DELAY;
717 				ng_pptpgre_start_send_ack_timer(node, maxWait);
718 			}
719 		}
720 
721 		/* Trim mbuf down to internal payload */
722 		m_adj(m, iphlen + grelen);
723 		if (extralen > 0)
724 			m_adj(m, -extralen);
725 
726 		/* Deliver frame to upper layers */
727 		NG_SEND_DATA(error, priv->upper, m, meta);
728 	} else {
729 		priv->stats.recvLoneAcks++;
730 		NG_FREE_DATA(m, meta);		/* no data to deliver */
731 	}
732 	return (error);
733 }
734 
735 /*************************************************************************
736 		    TIMER RELATED FUNCTIONS
737 *************************************************************************/
738 
739 /*
740  * Start a timer for the peer's acknowledging our oldest unacknowledged
741  * sequence number.  If we get an ack for this sequence number before
742  * the timer goes off, we cancel the timer.  Resets currently running
743  * recv ack timer, if any.
744  */
745 static void
746 ng_pptpgre_start_recv_ack_timer(node_p node)
747 {
748 	const priv_p priv = node->private;
749 	struct ng_pptpgre_ackp *const a = &priv->ackp;
750 	int remain, ticks;
751 
752 	/* Compute how long until oldest unack'd packet times out,
753 	   and reset the timer to that time. */
754 	KASSERT(a->rackTimerPtr == NULL, ("%s: rackTimer", __func__));
755 	remain = (a->timeSent[0] + a->ato) - ng_pptpgre_time(node);
756 	if (remain < 0)
757 		remain = 0;
758 #ifdef DEBUG_RAT
759 	a->timerLength = remain;
760 	a->timerStart = ng_pptpgre_time(node);
761 #endif
762 
763 	/* Start new timer */
764 	MALLOC(a->rackTimerPtr, node_p *, sizeof(node_p), M_NETGRAPH, M_NOWAIT);
765 	if (a->rackTimerPtr == NULL) {
766 		priv->stats.memoryFailures++;
767 		return;			/* XXX potential hang here */
768 	}
769 	*a->rackTimerPtr = node;	/* ensures the correct timeout event */
770 	node->refs++;
771 	priv->timers++;
772 
773 	/* Be conservative: timeout can happen up to 1 tick early */
774 	ticks = (((remain * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE) + 1;
775 	callout_reset(&a->rackTimer, ticks,
776 	    ng_pptpgre_recv_ack_timeout, a->rackTimerPtr);
777 }
778 
779 /*
780  * Stop receive ack timer.
781  */
782 static void
783 ng_pptpgre_stop_recv_ack_timer(node_p node)
784 {
785 	const priv_p priv = node->private;
786 	struct ng_pptpgre_ackp *const a = &priv->ackp;
787 
788 	if (callout_stop(&a->rackTimer)) {
789 		FREE(a->rackTimerPtr, M_NETGRAPH);
790 		priv->timers--;
791 		ng_unref(node);
792 	}
793 	a->rackTimerPtr = NULL;
794 }
795 
796 /*
797  * The peer has failed to acknowledge the oldest unacknowledged sequence
798  * number within the time allotted.  Update our adaptive timeout parameters
799  * and reset/restart the recv ack timer.
800  */
801 static void
802 ng_pptpgre_recv_ack_timeout(void *arg)
803 {
804 	const node_p node = *((node_p *)arg);
805 	const priv_p priv = node->private;
806 	struct ng_pptpgre_ackp *const a = &priv->ackp;
807 
808 	crit_enter();
809 	/* This complicated stuff is needed to avoid race conditions */
810 	FREE(arg, M_NETGRAPH);
811 	KASSERT(node->refs > 0, ("%s: no refs", __func__));
812 	KASSERT(priv != NULL, ("%s: priv=NULL", __func__));
813 	priv->timers--;
814 	if ((node->flags & NG_INVALID) != 0) {	/* shutdown race condition */
815 		if (priv->timers == 0) {
816 			FREE(priv, M_NETGRAPH);
817 			node->private = NULL;
818 		}
819 		ng_unref(node);
820 		crit_exit();
821 		return;
822 	}
823 	if (arg != a->rackTimerPtr) {	/* timer stopped race condition */
824 		ng_unref(node);
825 		crit_exit();
826 		return;
827 	}
828 	a->rackTimerPtr = NULL;
829 
830 	/* Update adaptive timeout stuff */
831 	priv->stats.recvAckTimeouts++;
832 	a->rtt = PPTP_ACK_DELTA(a->rtt);
833 	a->ato = a->rtt + PPTP_ACK_CHI(a->dev);
834 	if (a->ato > PPTP_MAX_TIMEOUT)
835 		a->ato = PPTP_MAX_TIMEOUT;
836 	if (a->ato < PPTP_MIN_TIMEOUT)
837 		a->ato = PPTP_MIN_TIMEOUT;
838 
839 #ifdef DEBUG_RAT
840     log(LOG_DEBUG,
841 	"RAT now=%d seq=0x%x sent=%d tstart=%d tlen=%d ato=%d\n",
842 	(int)ng_pptpgre_time(node), priv->recvAck + 1,
843 	(int)a->timeSent[0], (int)a->timerStart, (int)a->timerLength, a->ato);
844 #endif
845 
846 	/* Reset ack and sliding window */
847 	priv->recvAck = priv->xmitSeq;		/* pretend we got the ack */
848 	a->xmitWin = (a->xmitWin + 1) / 2;	/* shrink transmit window */
849 	a->winAck = priv->recvAck + a->xmitWin;	/* reset win expand time */
850 	ng_unref(node);
851 	crit_exit();
852 }
853 
854 /*
855  * Start the send ack timer. This assumes the timer is not
856  * already running.
857  */
858 static void
859 ng_pptpgre_start_send_ack_timer(node_p node, int ackTimeout)
860 {
861 	const priv_p priv = node->private;
862 	struct ng_pptpgre_ackp *const a = &priv->ackp;
863 	int ticks;
864 
865 	/* Start new timer */
866 	KASSERT(a->sackTimerPtr == NULL, ("%s: sackTimer", __func__));
867 	MALLOC(a->sackTimerPtr, node_p *, sizeof(node_p), M_NETGRAPH, M_NOWAIT);
868 	if (a->sackTimerPtr == NULL) {
869 		priv->stats.memoryFailures++;
870 		return;			/* XXX potential hang here */
871 	}
872 	*a->sackTimerPtr = node;	/* ensures the correct timeout event */
873 	node->refs++;
874 	priv->timers++;
875 
876 	/* Be conservative: timeout can happen up to 1 tick early */
877 	ticks = (((ackTimeout * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE);
878 	callout_reset(&a->sackTimer, ticks,
879 	    ng_pptpgre_send_ack_timeout, a->sackTimerPtr);
880 }
881 
882 /*
883  * Stop send ack timer.
884  */
885 static void
886 ng_pptpgre_stop_send_ack_timer(node_p node)
887 {
888 	const priv_p priv = node->private;
889 	struct ng_pptpgre_ackp *const a = &priv->ackp;
890 
891 	if (callout_stop(&a->sackTimer)) {
892 		FREE(a->sackTimerPtr, M_NETGRAPH);
893 		priv->timers--;
894 		ng_unref(node);
895 	}
896 	a->sackTimerPtr = NULL;
897 }
898 
899 /*
900  * We've waited as long as we're willing to wait before sending an
901  * acknowledgement to the peer for received frames. We had hoped to
902  * be able to piggy back our acknowledgement on an outgoing data frame,
903  * but apparently there haven't been any since. So send the ack now.
904  */
905 static void
906 ng_pptpgre_send_ack_timeout(void *arg)
907 {
908 	const node_p node = *((node_p *)arg);
909 	const priv_p priv = node->private;
910 	struct ng_pptpgre_ackp *const a = &priv->ackp;
911 
912 	crit_enter();
913 	/* This complicated stuff is needed to avoid race conditions */
914 	FREE(arg, M_NETGRAPH);
915 	KASSERT(node->refs > 0, ("%s: no refs", __func__));
916 	KASSERT(priv != NULL, ("%s: priv=NULL", __func__));
917 	priv->timers--;
918 	if ((node->flags & NG_INVALID) != 0) {	/* shutdown race condition */
919 		if (priv->timers == 0) {
920 			FREE(priv, M_NETGRAPH);
921 			node->private = NULL;
922 		}
923 		ng_unref(node);
924 		crit_exit();
925 		return;
926 	}
927 	if (a->sackTimerPtr != arg) {	/* timer stopped race condition */
928 		ng_unref(node);
929 		crit_exit();
930 		return;
931 	}
932 	a->sackTimerPtr = NULL;
933 
934 	/* Send a frame with an ack but no payload */
935   	ng_pptpgre_xmit(node, NULL, NULL);
936 	ng_unref(node);
937 	crit_exit();
938 }
939 
940 /*************************************************************************
941 		    MISC FUNCTIONS
942 *************************************************************************/
943 
944 /*
945  * Reset state
946  */
947 static void
948 ng_pptpgre_reset(node_p node)
949 {
950 	const priv_p priv = node->private;
951 	struct ng_pptpgre_ackp *const a = &priv->ackp;
952 
953 	/* Reset adaptive timeout state */
954 	a->ato = PPTP_MAX_TIMEOUT;
955 	a->rtt = priv->conf.peerPpd * PPTP_TIME_SCALE / 10;  /* ppd in 10ths */
956 	if (a->rtt < PPTP_MIN_RTT)
957 		a->rtt = PPTP_MIN_RTT;
958 	a->dev = 0;
959 	a->xmitWin = (priv->conf.recvWin + 1) / 2;
960 	if (a->xmitWin < 2)		/* often the first packet is lost */
961 		a->xmitWin = 2;		/*   because the peer isn't ready */
962 	if (a->xmitWin > PPTP_XMIT_WIN)
963 		a->xmitWin = PPTP_XMIT_WIN;
964 	a->winAck = a->xmitWin;
965 
966 	/* Reset sequence numbers */
967 	priv->recvSeq = ~0;
968 	priv->recvAck = ~0;
969 	priv->xmitSeq = ~0;
970 	priv->xmitAck = ~0;
971 
972 	/* Reset start time */
973 	getmicrouptime(&priv->startTime);
974 
975 	/* Reset stats */
976 	bzero(&priv->stats, sizeof(priv->stats));
977 
978 	/* Stop timers */
979 	ng_pptpgre_stop_send_ack_timer(node);
980 	ng_pptpgre_stop_recv_ack_timer(node);
981 }
982 
983 /*
984  * Return the current time scaled & translated to our internally used format.
985  */
986 static pptptime_t
987 ng_pptpgre_time(node_p node)
988 {
989 	const priv_p priv = node->private;
990 	struct timeval tv;
991 	pptptime_t t;
992 
993 	microuptime(&tv);
994 	if (tv.tv_sec < priv->startTime.tv_sec
995 	    || (tv.tv_sec == priv->startTime.tv_sec
996 	      && tv.tv_usec < priv->startTime.tv_usec))
997 		return (0);
998 	timevalsub(&tv, &priv->startTime);
999 	t = (pptptime_t)tv.tv_sec * PPTP_TIME_SCALE;
1000 	t += (pptptime_t)tv.tv_usec / (1000000 / PPTP_TIME_SCALE);
1001 	return(t);
1002 }
1003 
1004