For kmalloc(), MALLOC() and contigmalloc(), use M_ZERO instead of
[dragonfly.git] / sys / netgraph / pptpgre / ng_pptpgre.c
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