ng_l2tp.c revision 172562
1/*-
2 * Copyright (c) 2001-2002 Packet Design, LLC.
3 * All rights reserved.
4 *
5 * Subject to the following obligations and disclaimer of warranty,
6 * use and redistribution of this software, in source or object code
7 * forms, with or without modifications are expressly permitted by
8 * Packet Design; provided, however, that:
9 *
10 *    (i)  Any and all reproductions of the source or object code
11 *         must include the copyright notice above and the following
12 *         disclaimer of warranties; and
13 *    (ii) No rights are granted, in any manner or form, to use
14 *         Packet Design trademarks, including the mark "PACKET DESIGN"
15 *         on advertising, endorsements, or otherwise except as such
16 *         appears in the above copyright notice or in the software.
17 *
18 * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
19 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
20 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
21 * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
22 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
23 * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
24 * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
25 * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
26 * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
27 * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
28 * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
30 * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
31 * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
32 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
34 * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
35 * THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * Author: Archie Cobbs <archie@freebsd.org>
38 *
39 * $FreeBSD: head/sys/netgraph/ng_l2tp.c 172562 2007-10-12 04:51:30Z mav $
40 */
41
42/*
43 * L2TP netgraph node type.
44 *
45 * This node type implements the lower layer of the
46 * L2TP protocol as specified in RFC 2661.
47 */
48
49#include <sys/param.h>
50#include <sys/systm.h>
51#include <sys/kernel.h>
52#include <sys/time.h>
53#include <sys/conf.h>
54#include <sys/mbuf.h>
55#include <sys/malloc.h>
56#include <sys/errno.h>
57#include <sys/libkern.h>
58
59#include <netgraph/ng_message.h>
60#include <netgraph/netgraph.h>
61#include <netgraph/ng_parse.h>
62#include <netgraph/ng_l2tp.h>
63
64#ifdef NG_SEPARATE_MALLOC
65MALLOC_DEFINE(M_NETGRAPH_L2TP, "netgraph_l2tp", "netgraph l2tp node");
66#else
67#define M_NETGRAPH_L2TP M_NETGRAPH
68#endif
69
70/* L2TP header format (first 2 bytes only) */
71#define L2TP_HDR_CTRL		0x8000			/* control packet */
72#define L2TP_HDR_LEN		0x4000			/* has length field */
73#define L2TP_HDR_SEQ		0x0800			/* has ns, nr fields */
74#define L2TP_HDR_OFF		0x0200			/* has offset field */
75#define L2TP_HDR_PRIO		0x0100			/* give priority */
76#define L2TP_HDR_VERS_MASK	0x000f			/* version field mask */
77#define L2TP_HDR_VERSION	0x0002			/* version field */
78
79/* Bits that must be zero or one in first two bytes of header */
80#define L2TP_CTRL_0BITS		0x030d			/* ctrl: must be 0 */
81#define L2TP_CTRL_1BITS		0xc802			/* ctrl: must be 1 */
82#define L2TP_DATA_0BITS		0x800d			/* data: must be 0 */
83#define L2TP_DATA_1BITS		0x0002			/* data: must be 1 */
84
85/* Standard xmit ctrl and data header bits */
86#define L2TP_CTRL_HDR		(L2TP_HDR_CTRL | L2TP_HDR_LEN \
87				    | L2TP_HDR_SEQ | L2TP_HDR_VERSION)
88#define L2TP_DATA_HDR		(L2TP_HDR_VERSION)	/* optional: len, seq */
89
90/* Some hard coded values */
91#define L2TP_MAX_XWIN		16			/* my max xmit window */
92#define L2TP_MAX_REXMIT		5			/* default max rexmit */
93#define L2TP_MAX_REXMIT_TO	30			/* default rexmit to */
94#define L2TP_DELAYED_ACK	((hz + 19) / 20)	/* delayed ack: 50 ms */
95
96/* Default data sequence number configuration for new sessions */
97#define L2TP_CONTROL_DSEQ	1			/* we are the lns */
98#define L2TP_ENABLE_DSEQ	1			/* enable data seq # */
99
100/* Compare sequence numbers using circular math */
101#define L2TP_SEQ_DIFF(x, y)	((int)((int16_t)(x) - (int16_t)(y)))
102
103/*
104 * Sequence number state
105 *
106 * Invariants:
107 *    - If cwnd < ssth, we're doing slow start, otherwise congestion avoidance
108 *    - The number of unacknowledged xmit packets is (ns - rack) <= seq->wmax
109 *    - The first (ns - rack) mbuf's in xwin[] array are copies of these
110 *	unacknowledged packets; the remainder of xwin[] consists first of
111 *	zero or more further untransmitted packets in the transmit queue
112 *    - We try to keep the peer's receive window as full as possible.
113 *	Therefore, (i < cwnd && xwin[i] != NULL) implies (ns - rack) > i.
114 *    - rack_timer is running iff (ns - rack) > 0 (unack'd xmit'd pkts)
115 *    - If xack != nr, there are unacknowledged recv packet(s) (delayed ack)
116 *    - xack_timer is running iff xack != nr (unack'd rec'd pkts)
117 */
118struct l2tp_seq {
119	u_int16_t		ns;		/* next xmit seq we send */
120	u_int16_t		nr;		/* next recv seq we expect */
121	u_int16_t		rack;		/* last 'nr' we rec'd */
122	u_int16_t		xack;		/* last 'nr' we sent */
123	u_int16_t		wmax;		/* peer's max recv window */
124	u_int16_t		cwnd;		/* current congestion window */
125	u_int16_t		ssth;		/* slow start threshold */
126	u_int16_t		acks;		/* # consecutive acks rec'd */
127	u_int16_t		rexmits;	/* # retransmits sent */
128	struct callout		rack_timer;	/* retransmit timer */
129	struct callout		xack_timer;	/* delayed ack timer */
130	struct mbuf		*xwin[L2TP_MAX_XWIN];	/* transmit window */
131};
132
133/* Node private data */
134struct ng_l2tp_private {
135	node_p			node;		/* back pointer to node */
136	hook_p			ctrl;		/* hook to upper layers */
137	hook_p			lower;		/* hook to lower layers */
138	struct ng_l2tp_config	conf;		/* node configuration */
139	struct ng_l2tp_stats	stats;		/* node statistics */
140	struct l2tp_seq		seq;		/* ctrl sequence number state */
141	ng_ID_t			ftarget;	/* failure message target */
142};
143typedef struct ng_l2tp_private *priv_p;
144
145/* Hook private data (data session hooks only) */
146struct ng_l2tp_hook_private {
147	struct ng_l2tp_sess_config	conf;	/* hook/session config */
148	struct ng_l2tp_session_stats	stats;	/* per sessions statistics */
149	u_int16_t			ns;	/* data ns sequence number */
150	u_int16_t			nr;	/* data nr sequence number */
151};
152typedef struct ng_l2tp_hook_private *hookpriv_p;
153
154/* Netgraph node methods */
155static ng_constructor_t	ng_l2tp_constructor;
156static ng_rcvmsg_t	ng_l2tp_rcvmsg;
157static ng_shutdown_t	ng_l2tp_shutdown;
158static ng_newhook_t	ng_l2tp_newhook;
159static ng_rcvdata_t	ng_l2tp_rcvdata;
160static ng_disconnect_t	ng_l2tp_disconnect;
161
162/* Internal functions */
163static int	ng_l2tp_recv_lower(node_p node, item_p item);
164static int	ng_l2tp_recv_ctrl(node_p node, item_p item);
165static int	ng_l2tp_recv_data(node_p node, item_p item, hookpriv_p hpriv);
166
167static int	ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns);
168
169static void	ng_l2tp_seq_init(priv_p priv);
170static int	ng_l2tp_seq_set(priv_p priv,
171			const struct ng_l2tp_seq_config *conf);
172static int	ng_l2tp_seq_adjust(priv_p priv,
173			const struct ng_l2tp_config *conf);
174static void	ng_l2tp_seq_reset(priv_p priv);
175static void	ng_l2tp_seq_failure(priv_p priv);
176static void	ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr);
177static int	ng_l2tp_seq_recv_ns(priv_p priv, u_int16_t ns);
178static void	ng_l2tp_seq_xack_timeout(node_p node, hook_p hook,
179		    void *arg1, int arg2);
180static void	ng_l2tp_seq_rack_timeout(node_p node, hook_p hook,
181		    void *arg1, int arg2);
182
183static ng_fn_eachhook	ng_l2tp_find_session;
184static ng_fn_eachhook	ng_l2tp_reset_session;
185
186#ifdef INVARIANTS
187static void	ng_l2tp_seq_check(struct l2tp_seq *seq);
188#endif
189
190/* Parse type for struct ng_l2tp_seq_config. */
191static const struct ng_parse_struct_field
192	ng_l2tp_seq_config_fields[] = NG_L2TP_SEQ_CONFIG_TYPE_INFO;
193static const struct ng_parse_type ng_l2tp_seq_config_type = {
194	&ng_parse_struct_type,
195	&ng_l2tp_seq_config_fields
196};
197
198/* Parse type for struct ng_l2tp_config */
199static const struct ng_parse_struct_field
200	ng_l2tp_config_type_fields[] = NG_L2TP_CONFIG_TYPE_INFO;
201static const struct ng_parse_type ng_l2tp_config_type = {
202	&ng_parse_struct_type,
203	&ng_l2tp_config_type_fields,
204};
205
206/* Parse type for struct ng_l2tp_sess_config */
207static const struct ng_parse_struct_field
208	ng_l2tp_sess_config_type_fields[] = NG_L2TP_SESS_CONFIG_TYPE_INFO;
209static const struct ng_parse_type ng_l2tp_sess_config_type = {
210	&ng_parse_struct_type,
211	&ng_l2tp_sess_config_type_fields,
212};
213
214/* Parse type for struct ng_l2tp_stats */
215static const struct ng_parse_struct_field
216	ng_l2tp_stats_type_fields[] = NG_L2TP_STATS_TYPE_INFO;
217static const struct ng_parse_type ng_l2tp_stats_type = {
218	&ng_parse_struct_type,
219	&ng_l2tp_stats_type_fields
220};
221
222/* Parse type for struct ng_l2tp_session_stats. */
223static const struct ng_parse_struct_field
224	ng_l2tp_session_stats_type_fields[] = NG_L2TP_SESSION_STATS_TYPE_INFO;
225static const struct ng_parse_type ng_l2tp_session_stats_type = {
226	&ng_parse_struct_type,
227	&ng_l2tp_session_stats_type_fields
228};
229
230/* List of commands and how to convert arguments to/from ASCII */
231static const struct ng_cmdlist ng_l2tp_cmdlist[] = {
232	{
233	  NGM_L2TP_COOKIE,
234	  NGM_L2TP_SET_CONFIG,
235	  "setconfig",
236	  &ng_l2tp_config_type,
237	  NULL
238	},
239	{
240	  NGM_L2TP_COOKIE,
241	  NGM_L2TP_GET_CONFIG,
242	  "getconfig",
243	  NULL,
244	  &ng_l2tp_config_type
245	},
246	{
247	  NGM_L2TP_COOKIE,
248	  NGM_L2TP_SET_SESS_CONFIG,
249	  "setsessconfig",
250	  &ng_l2tp_sess_config_type,
251	  NULL
252	},
253	{
254	  NGM_L2TP_COOKIE,
255	  NGM_L2TP_GET_SESS_CONFIG,
256	  "getsessconfig",
257	  &ng_parse_hint16_type,
258	  &ng_l2tp_sess_config_type
259	},
260	{
261	  NGM_L2TP_COOKIE,
262	  NGM_L2TP_GET_STATS,
263	  "getstats",
264	  NULL,
265	  &ng_l2tp_stats_type
266	},
267	{
268	  NGM_L2TP_COOKIE,
269	  NGM_L2TP_CLR_STATS,
270	  "clrstats",
271	  NULL,
272	  NULL
273	},
274	{
275	  NGM_L2TP_COOKIE,
276	  NGM_L2TP_GETCLR_STATS,
277	  "getclrstats",
278	  NULL,
279	  &ng_l2tp_stats_type
280	},
281	{
282	  NGM_L2TP_COOKIE,
283	  NGM_L2TP_GET_SESSION_STATS,
284	  "getsessstats",
285	  &ng_parse_int16_type,
286	  &ng_l2tp_session_stats_type
287	},
288	{
289	  NGM_L2TP_COOKIE,
290	  NGM_L2TP_CLR_SESSION_STATS,
291	  "clrsessstats",
292	  &ng_parse_int16_type,
293	  NULL
294	},
295	{
296	  NGM_L2TP_COOKIE,
297	  NGM_L2TP_GETCLR_SESSION_STATS,
298	  "getclrsessstats",
299	  &ng_parse_int16_type,
300	  &ng_l2tp_session_stats_type
301	},
302	{
303	  NGM_L2TP_COOKIE,
304	  NGM_L2TP_ACK_FAILURE,
305	  "ackfailure",
306	  NULL,
307	  NULL
308	},
309	{
310	  NGM_L2TP_COOKIE,
311	  NGM_L2TP_SET_SEQ,
312	  "setsequence",
313	  &ng_l2tp_seq_config_type,
314	  NULL
315	},
316	{ 0 }
317};
318
319/* Node type descriptor */
320static struct ng_type ng_l2tp_typestruct = {
321	.version =	NG_ABI_VERSION,
322	.name =		NG_L2TP_NODE_TYPE,
323	.constructor =	ng_l2tp_constructor,
324	.rcvmsg =	ng_l2tp_rcvmsg,
325	.shutdown =	ng_l2tp_shutdown,
326	.newhook =	ng_l2tp_newhook,
327	.rcvdata =	ng_l2tp_rcvdata,
328	.disconnect =	ng_l2tp_disconnect,
329	.cmdlist =	ng_l2tp_cmdlist,
330};
331NETGRAPH_INIT(l2tp, &ng_l2tp_typestruct);
332
333/* Sequence number state sanity checking */
334#ifdef INVARIANTS
335#define L2TP_SEQ_CHECK(seq)	ng_l2tp_seq_check(seq)
336#else
337#define L2TP_SEQ_CHECK(x)	do { } while (0)
338#endif
339
340/* memmove macro */
341#define memmove(d, s, l)	bcopy(s, d, l)
342
343/* Whether to use m_copypacket() or m_dup() */
344#define L2TP_COPY_MBUF		m_copypacket
345
346/************************************************************************
347			NETGRAPH NODE STUFF
348************************************************************************/
349
350/*
351 * Node type constructor
352 */
353static int
354ng_l2tp_constructor(node_p node)
355{
356	priv_p priv;
357
358	/* Allocate private structure */
359	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH_L2TP, M_NOWAIT | M_ZERO);
360	if (priv == NULL)
361		return (ENOMEM);
362	NG_NODE_SET_PRIVATE(node, priv);
363	priv->node = node;
364
365	/* Apply a semi-reasonable default configuration */
366	priv->conf.peer_win = 1;
367	priv->conf.rexmit_max = L2TP_MAX_REXMIT;
368	priv->conf.rexmit_max_to = L2TP_MAX_REXMIT_TO;
369
370	/* Initialize sequence number state */
371	ng_l2tp_seq_init(priv);
372
373	/* Done */
374	return (0);
375}
376
377/*
378 * Give our OK for a hook to be added.
379 */
380static int
381ng_l2tp_newhook(node_p node, hook_p hook, const char *name)
382{
383	const priv_p priv = NG_NODE_PRIVATE(node);
384
385	/* Check hook name */
386	if (strcmp(name, NG_L2TP_HOOK_CTRL) == 0) {
387		if (priv->ctrl != NULL)
388			return (EISCONN);
389		priv->ctrl = hook;
390	} else if (strcmp(name, NG_L2TP_HOOK_LOWER) == 0) {
391		if (priv->lower != NULL)
392			return (EISCONN);
393		priv->lower = hook;
394	} else {
395		static const char hexdig[16] = "0123456789abcdef";
396		u_int16_t session_id;
397		hookpriv_p hpriv;
398		const char *hex;
399		int i;
400		int j;
401
402		/* Parse hook name to get session ID */
403		if (strncmp(name, NG_L2TP_HOOK_SESSION_P,
404		    sizeof(NG_L2TP_HOOK_SESSION_P) - 1) != 0)
405			return (EINVAL);
406		hex = name + sizeof(NG_L2TP_HOOK_SESSION_P) - 1;
407		for (session_id = i = 0; i < 4; i++) {
408			for (j = 0; j < 16 && hex[i] != hexdig[j]; j++);
409			if (j == 16)
410				return (EINVAL);
411			session_id = (session_id << 4) | j;
412		}
413		if (hex[i] != '\0')
414			return (EINVAL);
415
416		/* Create hook private structure */
417		MALLOC(hpriv, hookpriv_p,
418		    sizeof(*hpriv), M_NETGRAPH_L2TP, M_NOWAIT | M_ZERO);
419		if (hpriv == NULL)
420			return (ENOMEM);
421		hpriv->conf.session_id = htons(session_id);
422		hpriv->conf.control_dseq = L2TP_CONTROL_DSEQ;
423		hpriv->conf.enable_dseq = L2TP_ENABLE_DSEQ;
424		NG_HOOK_SET_PRIVATE(hook, hpriv);
425	}
426
427	/* Done */
428	return (0);
429}
430
431/*
432 * Receive a control message.
433 */
434static int
435ng_l2tp_rcvmsg(node_p node, item_p item, hook_p lasthook)
436{
437	const priv_p priv = NG_NODE_PRIVATE(node);
438	struct ng_mesg *resp = NULL;
439	struct ng_mesg *msg;
440	int error = 0;
441
442	NGI_GET_MSG(item, msg);
443	switch (msg->header.typecookie) {
444	case NGM_L2TP_COOKIE:
445		switch (msg->header.cmd) {
446		case NGM_L2TP_SET_CONFIG:
447		    {
448			struct ng_l2tp_config *const conf =
449				(struct ng_l2tp_config *)msg->data;
450
451			/* Check for invalid or illegal config */
452			if (msg->header.arglen != sizeof(*conf)) {
453				error = EINVAL;
454				break;
455			}
456			conf->enabled = !!conf->enabled;
457			conf->match_id = !!conf->match_id;
458			conf->tunnel_id = htons(conf->tunnel_id);
459			conf->peer_id = htons(conf->peer_id);
460			if (priv->conf.enabled
461			    && ((priv->conf.tunnel_id != 0
462			       && conf->tunnel_id != priv->conf.tunnel_id)
463			      || ((priv->conf.peer_id != 0
464			       && conf->peer_id != priv->conf.peer_id)))) {
465				error = EBUSY;
466				break;
467			}
468
469			/* Save calling node as failure target */
470			priv->ftarget = NGI_RETADDR(item);
471
472			/* Adjust sequence number state */
473			if ((error = ng_l2tp_seq_adjust(priv, conf)) != 0)
474				break;
475
476			/* Update node's config */
477			priv->conf = *conf;
478			break;
479		    }
480		case NGM_L2TP_GET_CONFIG:
481		    {
482			struct ng_l2tp_config *conf;
483
484			NG_MKRESPONSE(resp, msg, sizeof(*conf), M_NOWAIT);
485			if (resp == NULL) {
486				error = ENOMEM;
487				break;
488			}
489			conf = (struct ng_l2tp_config *)resp->data;
490			*conf = priv->conf;
491
492			/* Put ID's in host order */
493			conf->tunnel_id = ntohs(conf->tunnel_id);
494			conf->peer_id = ntohs(conf->peer_id);
495			break;
496		    }
497		case NGM_L2TP_SET_SESS_CONFIG:
498		    {
499			struct ng_l2tp_sess_config *const conf =
500			    (struct ng_l2tp_sess_config *)msg->data;
501			hookpriv_p hpriv;
502			hook_p hook;
503
504			/* Check for invalid or illegal config. */
505			if (msg->header.arglen != sizeof(*conf)) {
506				error = EINVAL;
507				break;
508			}
509
510			/* Put ID's in network order */
511			conf->session_id = htons(conf->session_id);
512			conf->peer_id = htons(conf->peer_id);
513
514			/* Find matching hook */
515			NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
516			    (void *)(uintptr_t)conf->session_id, hook);
517			if (hook == NULL) {
518				error = ENOENT;
519				break;
520			}
521			hpriv = NG_HOOK_PRIVATE(hook);
522
523			/* Update hook's config */
524			hpriv->conf = *conf;
525			break;
526		    }
527		case NGM_L2TP_GET_SESS_CONFIG:
528		    {
529			struct ng_l2tp_sess_config *conf;
530			u_int16_t session_id;
531			hookpriv_p hpriv;
532			hook_p hook;
533
534			/* Get session ID */
535			if (msg->header.arglen != sizeof(session_id)) {
536				error = EINVAL;
537				break;
538			}
539			memcpy(&session_id, msg->data, 2);
540			session_id = htons(session_id);
541
542			/* Find matching hook */
543			NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
544			    (void *)(uintptr_t)session_id, hook);
545			if (hook == NULL) {
546				error = ENOENT;
547				break;
548			}
549			hpriv = NG_HOOK_PRIVATE(hook);
550
551			/* Send response */
552			NG_MKRESPONSE(resp, msg, sizeof(hpriv->conf), M_NOWAIT);
553			if (resp == NULL) {
554				error = ENOMEM;
555				break;
556			}
557			conf = (struct ng_l2tp_sess_config *)resp->data;
558			*conf = hpriv->conf;
559
560			/* Put ID's in host order */
561			conf->session_id = ntohs(conf->session_id);
562			conf->peer_id = ntohs(conf->peer_id);
563			break;
564		    }
565		case NGM_L2TP_GET_STATS:
566		case NGM_L2TP_CLR_STATS:
567		case NGM_L2TP_GETCLR_STATS:
568		    {
569			if (msg->header.cmd != NGM_L2TP_CLR_STATS) {
570				NG_MKRESPONSE(resp, msg,
571				    sizeof(priv->stats), M_NOWAIT);
572				if (resp == NULL) {
573					error = ENOMEM;
574					break;
575				}
576				memcpy(resp->data,
577				    &priv->stats, sizeof(priv->stats));
578			}
579			if (msg->header.cmd != NGM_L2TP_GET_STATS)
580				memset(&priv->stats, 0, sizeof(priv->stats));
581			break;
582		    }
583		case NGM_L2TP_GET_SESSION_STATS:
584		case NGM_L2TP_CLR_SESSION_STATS:
585		case NGM_L2TP_GETCLR_SESSION_STATS:
586		    {
587			uint16_t session_id;
588			hookpriv_p hpriv;
589			hook_p hook;
590
591			/* Get session ID. */
592			if (msg->header.arglen != sizeof(session_id)) {
593				error = EINVAL;
594				break;
595			}
596			bcopy(msg->data, &session_id, sizeof(uint16_t));
597			session_id = htons(session_id);
598
599			/* Find matching hook. */
600			NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
601			    (void *)(uintptr_t)session_id, hook);
602			if (hook == NULL) {
603				error = ENOENT;
604				break;
605			}
606			hpriv = NG_HOOK_PRIVATE(hook);
607
608			if (msg->header.cmd != NGM_L2TP_CLR_SESSION_STATS) {
609				NG_MKRESPONSE(resp, msg,
610				    sizeof(hpriv->stats), M_NOWAIT);
611				if (resp == NULL) {
612					error = ENOMEM;
613					break;
614				}
615				bcopy(&hpriv->stats, resp->data,
616					sizeof(hpriv->stats));
617			}
618			if (msg->header.cmd != NGM_L2TP_GET_SESSION_STATS)
619				bzero(&hpriv->stats, sizeof(hpriv->stats));
620			break;
621		    }
622		case NGM_L2TP_SET_SEQ:
623		    {
624			struct ng_l2tp_seq_config *const conf =
625				(struct ng_l2tp_seq_config *)msg->data;
626
627			/* Check for invalid or illegal seq config. */
628			if (msg->header.arglen != sizeof(*conf)) {
629				error = EINVAL;
630				break;
631			}
632			conf->ns = htons(conf->ns);
633			conf->nr = htons(conf->nr);
634			conf->rack = htons(conf->rack);
635			conf->xack = htons(conf->xack);
636
637			/* Set sequence numbers. */
638			error = ng_l2tp_seq_set(priv, conf);
639			break;
640		    }
641		default:
642			error = EINVAL;
643			break;
644		}
645		break;
646	default:
647		error = EINVAL;
648		break;
649	}
650
651	/* Done */
652	NG_RESPOND_MSG(error, node, item, resp);
653	NG_FREE_MSG(msg);
654	return (error);
655}
656
657/*
658 * Receive incoming data on a hook.
659 */
660static int
661ng_l2tp_rcvdata(hook_p hook, item_p item)
662{
663	const node_p node = NG_HOOK_NODE(hook);
664	const priv_p priv = NG_NODE_PRIVATE(node);
665	int error;
666
667	/* Sanity check */
668	L2TP_SEQ_CHECK(&priv->seq);
669
670	/* If not configured, reject */
671	if (!priv->conf.enabled) {
672		NG_FREE_ITEM(item);
673		return (ENXIO);
674	}
675
676	/* Handle incoming frame from below */
677	if (hook == priv->lower) {
678		error = ng_l2tp_recv_lower(node, item);
679		goto done;
680	}
681
682	/* Handle outgoing control frame */
683	if (hook == priv->ctrl) {
684		error = ng_l2tp_recv_ctrl(node, item);
685		goto done;
686	}
687
688	/* Handle outgoing data frame */
689	error = ng_l2tp_recv_data(node, item, NG_HOOK_PRIVATE(hook));
690
691done:
692	/* Done */
693	L2TP_SEQ_CHECK(&priv->seq);
694	return (error);
695}
696
697/*
698 * Destroy node
699 */
700static int
701ng_l2tp_shutdown(node_p node)
702{
703	const priv_p priv = NG_NODE_PRIVATE(node);
704	struct l2tp_seq *const seq = &priv->seq;
705
706	/* Sanity check */
707	L2TP_SEQ_CHECK(seq);
708
709	/* Reset sequence number state */
710	ng_l2tp_seq_reset(priv);
711
712	/* Free private data if neither timer is running */
713	ng_uncallout(&seq->rack_timer, node);
714	ng_uncallout(&seq->xack_timer, node);
715
716	FREE(priv, M_NETGRAPH_L2TP);
717
718	/* Unref node */
719	NG_NODE_UNREF(node);
720	return (0);
721}
722
723/*
724 * Hook disconnection
725 */
726static int
727ng_l2tp_disconnect(hook_p hook)
728{
729	const node_p node = NG_HOOK_NODE(hook);
730	const priv_p priv = NG_NODE_PRIVATE(node);
731
732	/* Zero out hook pointer */
733	if (hook == priv->ctrl)
734		priv->ctrl = NULL;
735	else if (hook == priv->lower)
736		priv->lower = NULL;
737	else {
738		FREE(NG_HOOK_PRIVATE(hook), M_NETGRAPH_L2TP);
739		NG_HOOK_SET_PRIVATE(hook, NULL);
740	}
741
742	/* Go away if no longer connected to anything */
743	if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node))
744		ng_rmnode_self(node);
745	return (0);
746}
747
748/*************************************************************************
749			INTERNAL FUNCTIONS
750*************************************************************************/
751
752/*
753 * Find the hook with a given session ID.
754 */
755static int
756ng_l2tp_find_session(hook_p hook, void *arg)
757{
758	const hookpriv_p hpriv = NG_HOOK_PRIVATE(hook);
759	const u_int16_t sid = (u_int16_t)(uintptr_t)arg;
760
761	if (hpriv == NULL || hpriv->conf.session_id != sid)
762		return (-1);
763	return (0);
764}
765
766/*
767 * Reset a hook's session state.
768 */
769static int
770ng_l2tp_reset_session(hook_p hook, void *arg)
771{
772	const hookpriv_p hpriv = NG_HOOK_PRIVATE(hook);
773
774	if (hpriv != NULL) {
775		hpriv->conf.control_dseq = 0;
776		hpriv->conf.enable_dseq = 0;
777		bzero(&hpriv->conf, sizeof(struct ng_l2tp_session_stats));
778		hpriv->nr = 0;
779		hpriv->ns = 0;
780	}
781	return (-1);
782}
783
784/*
785 * Handle an incoming frame from below.
786 */
787static int
788ng_l2tp_recv_lower(node_p node, item_p item)
789{
790	static const u_int16_t req_bits[2][2] = {
791		{ L2TP_DATA_0BITS, L2TP_DATA_1BITS },
792		{ L2TP_CTRL_0BITS, L2TP_CTRL_1BITS },
793	};
794	const priv_p priv = NG_NODE_PRIVATE(node);
795	hookpriv_p hpriv = NULL;
796	hook_p hook = NULL;
797	u_int16_t ids[2];
798	struct mbuf *m;
799	u_int16_t hdr;
800	u_int16_t ns;
801	u_int16_t nr;
802	int is_ctrl;
803	int error;
804	int len, plen;
805
806	/* Grab mbuf */
807	NGI_GET_M(item, m);
808
809	/* Remember full packet length; needed for per session accounting. */
810	plen = m->m_pkthdr.len;
811
812	/* Update stats */
813	priv->stats.recvPackets++;
814	priv->stats.recvOctets += plen;
815
816	/* Get initial header */
817	if (m->m_pkthdr.len < 6) {
818		priv->stats.recvRunts++;
819		NG_FREE_ITEM(item);
820		NG_FREE_M(m);
821		return (EINVAL);
822	}
823	if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
824		priv->stats.memoryFailures++;
825		NG_FREE_ITEM(item);
826		return (EINVAL);
827	}
828	hdr = ntohs(*mtod(m, u_int16_t *));
829	m_adj(m, 2);
830
831	/* Check required header bits and minimum length */
832	is_ctrl = (hdr & L2TP_HDR_CTRL) != 0;
833	if ((hdr & req_bits[is_ctrl][0]) != 0
834	    || (~hdr & req_bits[is_ctrl][1]) != 0) {
835		priv->stats.recvInvalid++;
836		NG_FREE_ITEM(item);
837		NG_FREE_M(m);
838		return (EINVAL);
839	}
840	if (m->m_pkthdr.len < 4				/* tunnel, session id */
841	    + (2 * ((hdr & L2TP_HDR_LEN) != 0))		/* length field */
842	    + (4 * ((hdr & L2TP_HDR_SEQ) != 0))		/* seq # fields */
843	    + (2 * ((hdr & L2TP_HDR_OFF) != 0))) {	/* offset field */
844		priv->stats.recvRunts++;
845		NG_FREE_ITEM(item);
846		NG_FREE_M(m);
847		return (EINVAL);
848	}
849
850	/* Get and validate length field if present */
851	if ((hdr & L2TP_HDR_LEN) != 0) {
852		if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
853			priv->stats.memoryFailures++;
854			NG_FREE_ITEM(item);
855			return (EINVAL);
856		}
857		len = (u_int16_t)ntohs(*mtod(m, u_int16_t *)) - 4;
858		m_adj(m, 2);
859		if (len < 0 || len > m->m_pkthdr.len) {
860			priv->stats.recvInvalid++;
861			NG_FREE_ITEM(item);
862			NG_FREE_M(m);
863			return (EINVAL);
864		}
865		if (len < m->m_pkthdr.len)		/* trim extra bytes */
866			m_adj(m, -(m->m_pkthdr.len - len));
867	}
868
869	/* Get tunnel ID and session ID */
870	if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
871		priv->stats.memoryFailures++;
872		NG_FREE_ITEM(item);
873		return (EINVAL);
874	}
875	memcpy(ids, mtod(m, u_int16_t *), 4);
876	m_adj(m, 4);
877
878	/* Check tunnel ID */
879	if (ids[0] != priv->conf.tunnel_id
880	    && (priv->conf.match_id || ids[0] != 0)) {
881		priv->stats.recvWrongTunnel++;
882		NG_FREE_ITEM(item);
883		NG_FREE_M(m);
884		return (EADDRNOTAVAIL);
885	}
886
887	/* Check session ID (for data packets only) */
888	if ((hdr & L2TP_HDR_CTRL) == 0) {
889		NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
890		    (void *)(uintptr_t)ids[1], hook);
891		if (hook == NULL) {
892			priv->stats.recvUnknownSID++;
893			NG_FREE_ITEM(item);
894			NG_FREE_M(m);
895			return (ENOTCONN);
896		}
897		hpriv = NG_HOOK_PRIVATE(hook);
898	}
899
900	/* Get Ns, Nr fields if present */
901	if ((hdr & L2TP_HDR_SEQ) != 0) {
902		if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
903			priv->stats.memoryFailures++;
904			NG_FREE_ITEM(item);
905			return (EINVAL);
906		}
907		memcpy(&ns, &mtod(m, u_int16_t *)[0], 2);
908		ns = ntohs(ns);
909		memcpy(&nr, &mtod(m, u_int16_t *)[1], 2);
910		nr = ntohs(nr);
911		m_adj(m, 4);
912	}
913
914	/* Strip offset padding if present */
915	if ((hdr & L2TP_HDR_OFF) != 0) {
916		u_int16_t offset;
917
918		/* Get length of offset padding */
919		if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
920			priv->stats.memoryFailures++;
921			NG_FREE_ITEM(item);
922			return (EINVAL);
923		}
924		memcpy(&offset, mtod(m, u_int16_t *), 2);
925		offset = ntohs(offset);
926
927		/* Trim offset padding */
928		if ((2+offset) > m->m_pkthdr.len) {
929			priv->stats.recvInvalid++;
930			NG_FREE_ITEM(item);
931			NG_FREE_M(m);
932			return (EINVAL);
933		}
934		m_adj(m, 2+offset);
935	}
936
937	/* Handle control packets */
938	if ((hdr & L2TP_HDR_CTRL) != 0) {
939
940		/* Handle receive ack sequence number Nr */
941		ng_l2tp_seq_recv_nr(priv, nr);
942
943		/* Discard ZLB packets */
944		if (m->m_pkthdr.len == 0) {
945			priv->stats.recvZLBs++;
946			NG_FREE_ITEM(item);
947			NG_FREE_M(m);
948			return (0);
949		}
950
951		/*
952		 * Prepend session ID to packet here: we don't want to accept
953		 * the send sequence number Ns if we have to drop the packet
954		 * later because of a memory error, because then the upper
955		 * layer would never get the packet.
956		 */
957		M_PREPEND(m, 2, M_DONTWAIT);
958		if (m == NULL) {
959			priv->stats.memoryFailures++;
960			NG_FREE_ITEM(item);
961			return (ENOBUFS);
962		}
963		memcpy(mtod(m, u_int16_t *), &ids[1], 2);
964
965		/* Now handle send sequence number */
966		if (ng_l2tp_seq_recv_ns(priv, ns) == -1) {
967			NG_FREE_ITEM(item);
968			NG_FREE_M(m);
969			return (0);
970		}
971
972		/* Deliver packet to upper layers */
973		NG_FWD_NEW_DATA(error, item, priv->ctrl, m);
974		return (error);
975	}
976
977	/* Per session packet, account it. */
978	hpriv->stats.recvPackets++;
979	hpriv->stats.recvOctets += plen;
980
981	/* Follow peer's lead in data sequencing, if configured to do so */
982	if (!hpriv->conf.control_dseq)
983		hpriv->conf.enable_dseq = ((hdr & L2TP_HDR_SEQ) != 0);
984
985	/* Handle data sequence numbers if present and enabled */
986	if ((hdr & L2TP_HDR_SEQ) != 0) {
987		if (hpriv->conf.enable_dseq
988		    && L2TP_SEQ_DIFF(ns, hpriv->nr) < 0) {
989			NG_FREE_ITEM(item);	/* duplicate or out of order */
990			NG_FREE_M(m);
991			priv->stats.recvDataDrops++;
992			return (0);
993		}
994		hpriv->nr = ns + 1;
995	}
996
997	/* Drop empty data packets */
998	if (m->m_pkthdr.len == 0) {
999		NG_FREE_ITEM(item);
1000		NG_FREE_M(m);
1001		return (0);
1002	}
1003
1004	/* Deliver data */
1005	NG_FWD_NEW_DATA(error, item, hook, m);
1006	return (error);
1007}
1008
1009/*
1010 * Handle an outgoing control frame.
1011 */
1012static int
1013ng_l2tp_recv_ctrl(node_p node, item_p item)
1014{
1015	const priv_p priv = NG_NODE_PRIVATE(node);
1016	struct l2tp_seq *const seq = &priv->seq;
1017	struct mbuf *m;
1018	int i;
1019
1020	/* Grab mbuf and discard other stuff XXX */
1021	NGI_GET_M(item, m);
1022	NG_FREE_ITEM(item);
1023
1024	/* Packet should have session ID prepended */
1025	if (m->m_pkthdr.len < 2) {
1026		priv->stats.xmitInvalid++;
1027		m_freem(m);
1028		return (EINVAL);
1029	}
1030
1031	/* Check max length */
1032	if (m->m_pkthdr.len >= 0x10000 - 14) {
1033		priv->stats.xmitTooBig++;
1034		m_freem(m);
1035		return (EOVERFLOW);
1036	}
1037
1038	/* Find next empty slot in transmit queue */
1039	for (i = 0; i < L2TP_MAX_XWIN && seq->xwin[i] != NULL; i++);
1040	if (i == L2TP_MAX_XWIN) {
1041		priv->stats.xmitDrops++;
1042		m_freem(m);
1043		return (ENOBUFS);
1044	}
1045	seq->xwin[i] = m;
1046
1047	/* Sanity check receive ack timer state */
1048	KASSERT((i == 0) ^ callout_active(&seq->rack_timer),
1049	    ("%s: xwin %d full but rack timer %s running",
1050	    __func__, i, callout_active(&seq->rack_timer) ? "" : "not "));
1051
1052	/* If peer's receive window is already full, nothing else to do */
1053	if (i >= seq->cwnd)
1054		return (0);
1055
1056	/* Start retransmit timer if not already running */
1057	if (!callout_active(&seq->rack_timer))
1058		ng_callout(&seq->rack_timer, node, NULL,
1059		    hz, ng_l2tp_seq_rack_timeout, NULL, 0);
1060
1061	/* Copy packet */
1062	if ((m = L2TP_COPY_MBUF(seq->xwin[i], M_DONTWAIT)) == NULL) {
1063		priv->stats.memoryFailures++;
1064		return (ENOBUFS);
1065	}
1066
1067	/* Send packet and increment xmit sequence number */
1068	return (ng_l2tp_xmit_ctrl(priv, m, seq->ns++));
1069}
1070
1071/*
1072 * Handle an outgoing data frame.
1073 */
1074static int
1075ng_l2tp_recv_data(node_p node, item_p item, hookpriv_p hpriv)
1076{
1077	const priv_p priv = NG_NODE_PRIVATE(node);
1078	struct mbuf *m;
1079	u_int16_t hdr;
1080	int error;
1081	int i = 1;
1082
1083	/* Get mbuf */
1084	NGI_GET_M(item, m);
1085
1086	/* Check max length */
1087	if (m->m_pkthdr.len >= 0x10000 - 12) {
1088		priv->stats.xmitDataTooBig++;
1089		NG_FREE_ITEM(item);
1090		NG_FREE_M(m);
1091		return (EOVERFLOW);
1092	}
1093
1094	/* Prepend L2TP header */
1095	M_PREPEND(m, 6
1096	    + (2 * (hpriv->conf.include_length != 0))
1097	    + (4 * (hpriv->conf.enable_dseq != 0)),
1098	    M_DONTWAIT);
1099	if (m == NULL) {
1100		priv->stats.memoryFailures++;
1101		NG_FREE_ITEM(item);
1102		return (ENOBUFS);
1103	}
1104	hdr = L2TP_DATA_HDR;
1105	if (hpriv->conf.include_length) {
1106		hdr |= L2TP_HDR_LEN;
1107		mtod(m, u_int16_t *)[i++] = htons(m->m_pkthdr.len);
1108	}
1109	mtod(m, u_int16_t *)[i++] = priv->conf.peer_id;
1110	mtod(m, u_int16_t *)[i++] = hpriv->conf.peer_id;
1111	if (hpriv->conf.enable_dseq) {
1112		hdr |= L2TP_HDR_SEQ;
1113		mtod(m, u_int16_t *)[i++] = htons(hpriv->ns);
1114		mtod(m, u_int16_t *)[i++] = htons(hpriv->nr);
1115		hpriv->ns++;
1116	}
1117	mtod(m, u_int16_t *)[0] = htons(hdr);
1118
1119	/* Update per session stats. */
1120	hpriv->stats.xmitPackets++;
1121	hpriv->stats.xmitOctets += m->m_pkthdr.len;
1122
1123	/* And the global one. */
1124	priv->stats.xmitPackets++;
1125	priv->stats.xmitOctets += m->m_pkthdr.len;
1126
1127	/* Send packet */
1128	NG_FWD_NEW_DATA(error, item, priv->lower, m);
1129	return (error);
1130}
1131
1132/*
1133 * Send a message to our controlling node that we've failed.
1134 */
1135static void
1136ng_l2tp_seq_failure(priv_p priv)
1137{
1138	struct ng_mesg *msg;
1139	int error;
1140
1141	NG_MKMESSAGE(msg, NGM_L2TP_COOKIE, NGM_L2TP_ACK_FAILURE, 0, M_NOWAIT);
1142	if (msg == NULL)
1143		return;
1144	NG_SEND_MSG_ID(error, priv->node, msg, priv->ftarget, 0);
1145}
1146
1147/************************************************************************
1148			SEQUENCE NUMBER HANDLING
1149************************************************************************/
1150
1151/*
1152 * Initialize sequence number state.
1153 */
1154static void
1155ng_l2tp_seq_init(priv_p priv)
1156{
1157	struct l2tp_seq *const seq = &priv->seq;
1158
1159	KASSERT(priv->conf.peer_win >= 1,
1160	    ("%s: peer_win is zero", __func__));
1161	memset(seq, 0, sizeof(*seq));
1162	seq->cwnd = 1;
1163	seq->wmax = priv->conf.peer_win;
1164	if (seq->wmax > L2TP_MAX_XWIN)
1165		seq->wmax = L2TP_MAX_XWIN;
1166	seq->ssth = seq->wmax;
1167	ng_callout_init(&seq->rack_timer);
1168	ng_callout_init(&seq->xack_timer);
1169	L2TP_SEQ_CHECK(seq);
1170}
1171
1172/*
1173 * Set sequence number state as given from user.
1174 */
1175static int
1176ng_l2tp_seq_set(priv_p priv, const struct ng_l2tp_seq_config *conf)
1177{
1178	struct l2tp_seq *const seq = &priv->seq;
1179
1180	/* If node is enabled, deny update to sequence numbers. */
1181	if (priv->conf.enabled)
1182		return (EBUSY);
1183
1184	/* We only can handle the simple cases. */
1185	if (conf->xack != conf->nr || conf->ns != conf->rack)
1186		return (EINVAL);
1187
1188	/* Set ns,nr,rack,xack parameters. */
1189	seq->ns = conf->ns;
1190	seq->nr = conf->nr;
1191	seq->rack = conf->rack;
1192	seq->xack = conf->xack;
1193
1194	return (0);
1195}
1196
1197/*
1198 * Adjust sequence number state accordingly after reconfiguration.
1199 */
1200static int
1201ng_l2tp_seq_adjust(priv_p priv, const struct ng_l2tp_config *conf)
1202{
1203	struct l2tp_seq *const seq = &priv->seq;
1204	u_int16_t new_wmax;
1205
1206	/* If disabling node, reset state sequence number */
1207	if (!conf->enabled) {
1208		ng_l2tp_seq_reset(priv);
1209		return (0);
1210	}
1211
1212	/* Adjust peer's max recv window; it can only increase */
1213	new_wmax = conf->peer_win;
1214	if (new_wmax > L2TP_MAX_XWIN)
1215		new_wmax = L2TP_MAX_XWIN;
1216	if (new_wmax == 0)
1217		return (EINVAL);
1218	if (new_wmax < seq->wmax)
1219		return (EBUSY);
1220	seq->wmax = new_wmax;
1221
1222	/* Done */
1223	return (0);
1224}
1225
1226/*
1227 * Reset sequence number state.
1228 */
1229static void
1230ng_l2tp_seq_reset(priv_p priv)
1231{
1232	struct l2tp_seq *const seq = &priv->seq;
1233	hook_p hook;
1234	int i;
1235
1236	/* Sanity check */
1237	L2TP_SEQ_CHECK(seq);
1238
1239	/* Stop timers */
1240	ng_uncallout(&seq->rack_timer, priv->node);
1241	ng_uncallout(&seq->xack_timer, priv->node);
1242
1243	/* Free retransmit queue */
1244	for (i = 0; i < L2TP_MAX_XWIN; i++) {
1245		if (seq->xwin[i] == NULL)
1246			break;
1247		m_freem(seq->xwin[i]);
1248	}
1249
1250	/* Reset session hooks' sequence number states */
1251	NG_NODE_FOREACH_HOOK(priv->node, ng_l2tp_reset_session, NULL, hook);
1252
1253	/* Reset node's sequence number state */
1254	memset(seq, 0, sizeof(*seq));
1255	seq->cwnd = 1;
1256	seq->wmax = L2TP_MAX_XWIN;
1257	seq->ssth = seq->wmax;
1258
1259	/* Done */
1260	L2TP_SEQ_CHECK(seq);
1261}
1262
1263/*
1264 * Handle receipt of an acknowledgement value (Nr) from peer.
1265 */
1266static void
1267ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr)
1268{
1269	struct l2tp_seq *const seq = &priv->seq;
1270	struct mbuf *m;
1271	int nack;
1272	int i;
1273
1274	/* Verify peer's ACK is in range */
1275	if ((nack = L2TP_SEQ_DIFF(nr, seq->rack)) <= 0)
1276		return;				/* duplicate ack */
1277	if (L2TP_SEQ_DIFF(nr, seq->ns) > 0) {
1278		priv->stats.recvBadAcks++;	/* ack for packet not sent */
1279		return;
1280	}
1281	KASSERT(nack <= L2TP_MAX_XWIN,
1282	    ("%s: nack=%d > %d", __func__, nack, L2TP_MAX_XWIN));
1283
1284	/* Update receive ack stats */
1285	seq->rack = nr;
1286	seq->rexmits = 0;
1287
1288	/* Free acknowledged packets and shift up packets in the xmit queue */
1289	for (i = 0; i < nack; i++)
1290		m_freem(seq->xwin[i]);
1291	memmove(seq->xwin, seq->xwin + nack,
1292	    (L2TP_MAX_XWIN - nack) * sizeof(*seq->xwin));
1293	memset(seq->xwin + (L2TP_MAX_XWIN - nack), 0,
1294	    nack * sizeof(*seq->xwin));
1295
1296	/*
1297	 * Do slow-start/congestion avoidance windowing algorithm described
1298	 * in RFC 2661, Appendix A. Here we handle a multiple ACK as if each
1299	 * ACK had arrived separately.
1300	 */
1301	if (seq->cwnd < seq->wmax) {
1302
1303		/* Handle slow start phase */
1304		if (seq->cwnd < seq->ssth) {
1305			seq->cwnd += nack;
1306			nack = 0;
1307			if (seq->cwnd > seq->ssth) {	/* into cg.av. phase */
1308				nack = seq->cwnd - seq->ssth;
1309				seq->cwnd = seq->ssth;
1310			}
1311		}
1312
1313		/* Handle congestion avoidance phase */
1314		if (seq->cwnd >= seq->ssth) {
1315			seq->acks += nack;
1316			while (seq->acks >= seq->cwnd) {
1317				seq->acks -= seq->cwnd;
1318				if (seq->cwnd < seq->wmax)
1319					seq->cwnd++;
1320			}
1321		}
1322	}
1323
1324	/* Stop xmit timer */
1325	if (callout_active(&seq->rack_timer))
1326		ng_uncallout(&seq->rack_timer, priv->node);
1327
1328	/* If transmit queue is empty, we're done for now */
1329	if (seq->xwin[0] == NULL)
1330		return;
1331
1332	/* Start restransmit timer again */
1333	ng_callout(&seq->rack_timer, priv->node, NULL,
1334	    hz, ng_l2tp_seq_rack_timeout, NULL, 0);
1335
1336	/*
1337	 * Send more packets, trying to keep peer's receive window full.
1338	 * If there is a memory error, pretend packet was sent, as it
1339	 * will get retransmitted later anyway.
1340	 */
1341	while ((i = L2TP_SEQ_DIFF(seq->ns, seq->rack)) < seq->cwnd
1342	    && seq->xwin[i] != NULL) {
1343		if ((m = L2TP_COPY_MBUF(seq->xwin[i], M_DONTWAIT)) == NULL)
1344			priv->stats.memoryFailures++;
1345		else
1346			ng_l2tp_xmit_ctrl(priv, m, seq->ns);
1347		seq->ns++;
1348	}
1349}
1350
1351/*
1352 * Handle receipt of a sequence number value (Ns) from peer.
1353 * We make no attempt to re-order out of order packets.
1354 *
1355 * This function should only be called for non-ZLB packets.
1356 *
1357 * Returns:
1358 *	 0	Accept packet
1359 *	-1	Drop packet
1360 */
1361static int
1362ng_l2tp_seq_recv_ns(priv_p priv, u_int16_t ns)
1363{
1364	struct l2tp_seq *const seq = &priv->seq;
1365
1366	/* If not what we expect, drop packet and send an immediate ZLB ack */
1367	if (ns != seq->nr) {
1368		if (L2TP_SEQ_DIFF(ns, seq->nr) < 0)
1369			priv->stats.recvDuplicates++;
1370		else
1371			priv->stats.recvOutOfOrder++;
1372		ng_l2tp_xmit_ctrl(priv, NULL, seq->ns);
1373		return (-1);
1374	}
1375
1376	/* Update recv sequence number */
1377	seq->nr++;
1378
1379	/* Start receive ack timer, if not already running */
1380	if (!callout_active(&seq->xack_timer))
1381		ng_callout(&seq->xack_timer, priv->node, NULL,
1382		    L2TP_DELAYED_ACK, ng_l2tp_seq_xack_timeout, NULL, 0);
1383
1384	/* Accept packet */
1385	return (0);
1386}
1387
1388/*
1389 * Handle an ack timeout. We have an outstanding ack that we
1390 * were hoping to piggy-back, but haven't, so send a ZLB.
1391 */
1392static void
1393ng_l2tp_seq_xack_timeout(node_p node, hook_p hook, void *arg1, int arg2)
1394{
1395	const priv_p priv = NG_NODE_PRIVATE(node);
1396	struct l2tp_seq *const seq = &priv->seq;
1397
1398	/* Make sure callout is still active before doing anything */
1399	if (callout_pending(&seq->xack_timer) ||
1400	    (!callout_active(&seq->xack_timer)))
1401		return;
1402
1403	/* Sanity check */
1404	L2TP_SEQ_CHECK(seq);
1405
1406	/* Send a ZLB */
1407	ng_l2tp_xmit_ctrl(priv, NULL, seq->ns);
1408
1409	/* callout_deactivate() is not needed here
1410	    as ng_uncallout() was called by ng_l2tp_xmit_ctrl() */
1411
1412	/* Sanity check */
1413	L2TP_SEQ_CHECK(seq);
1414}
1415
1416/*
1417 * Handle a transmit timeout. The peer has failed to respond
1418 * with an ack for our packet, so retransmit it.
1419 */
1420static void
1421ng_l2tp_seq_rack_timeout(node_p node, hook_p hook, void *arg1, int arg2)
1422{
1423	const priv_p priv = NG_NODE_PRIVATE(node);
1424	struct l2tp_seq *const seq = &priv->seq;
1425	struct mbuf *m;
1426	u_int delay;
1427
1428	/* Make sure callout is still active before doing anything */
1429	if (callout_pending(&seq->rack_timer) ||
1430	    (!callout_active(&seq->rack_timer)))
1431		return;
1432
1433	/* Sanity check */
1434	L2TP_SEQ_CHECK(seq);
1435
1436	priv->stats.xmitRetransmits++;
1437
1438	/* Have we reached the retransmit limit? If so, notify owner. */
1439	if (seq->rexmits++ >= priv->conf.rexmit_max)
1440		ng_l2tp_seq_failure(priv);
1441
1442	/* Restart timer, this time with an increased delay */
1443	delay = (seq->rexmits > 12) ? (1 << 12) : (1 << seq->rexmits);
1444	if (delay > priv->conf.rexmit_max_to)
1445		delay = priv->conf.rexmit_max_to;
1446	ng_callout(&seq->rack_timer, node, NULL,
1447	    hz * delay, ng_l2tp_seq_rack_timeout, NULL, 0);
1448
1449	/* Do slow-start/congestion algorithm windowing algorithm */
1450	seq->ssth = (seq->cwnd + 1) / 2;
1451	seq->cwnd = 1;
1452	seq->acks = 0;
1453
1454	/* Retransmit oldest unack'd packet */
1455	if ((m = L2TP_COPY_MBUF(seq->xwin[0], M_DONTWAIT)) == NULL)
1456		priv->stats.memoryFailures++;
1457	else
1458		ng_l2tp_xmit_ctrl(priv, m, seq->rack);
1459
1460	/* callout_deactivate() is not needed here
1461	    as ng_callout() is getting called each time */
1462
1463	/* Sanity check */
1464	L2TP_SEQ_CHECK(seq);
1465}
1466
1467/*
1468 * Transmit a control stream packet, payload optional.
1469 * The transmit sequence number is not incremented.
1470 */
1471static int
1472ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns)
1473{
1474	struct l2tp_seq *const seq = &priv->seq;
1475	u_int16_t session_id = 0;
1476	int error;
1477
1478	/* Stop ack timer: we're sending an ack with this packet.
1479	   Doing this before to keep state predictable after error. */
1480	if (callout_active(&seq->xack_timer))
1481		ng_uncallout(&seq->xack_timer, priv->node);
1482
1483	seq->xack = seq->nr;
1484
1485	/* If no mbuf passed, send an empty packet (ZLB) */
1486	if (m == NULL) {
1487
1488		/* Create a new mbuf for ZLB packet */
1489		MGETHDR(m, M_DONTWAIT, MT_DATA);
1490		if (m == NULL) {
1491			priv->stats.memoryFailures++;
1492			return (ENOBUFS);
1493		}
1494		m->m_len = m->m_pkthdr.len = 12;
1495		m->m_pkthdr.rcvif = NULL;
1496		priv->stats.xmitZLBs++;
1497	} else {
1498
1499		/* Strip off session ID */
1500		if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
1501			priv->stats.memoryFailures++;
1502			return (ENOBUFS);
1503		}
1504		memcpy(&session_id, mtod(m, u_int16_t *), 2);
1505		m_adj(m, 2);
1506
1507		/* Make room for L2TP header */
1508		M_PREPEND(m, 12, M_DONTWAIT);
1509		if (m == NULL) {
1510			priv->stats.memoryFailures++;
1511			return (ENOBUFS);
1512		}
1513	}
1514
1515	/* Fill in L2TP header */
1516	mtod(m, u_int16_t *)[0] = htons(L2TP_CTRL_HDR);
1517	mtod(m, u_int16_t *)[1] = htons(m->m_pkthdr.len);
1518	mtod(m, u_int16_t *)[2] = priv->conf.peer_id;
1519	mtod(m, u_int16_t *)[3] = session_id;
1520	mtod(m, u_int16_t *)[4] = htons(ns);
1521	mtod(m, u_int16_t *)[5] = htons(seq->nr);
1522
1523	/* Update sequence number info and stats */
1524	priv->stats.xmitPackets++;
1525	priv->stats.xmitOctets += m->m_pkthdr.len;
1526
1527	/* Send packet */
1528	NG_SEND_DATA_ONLY(error, priv->lower, m);
1529	return (error);
1530}
1531
1532#ifdef INVARIANTS
1533/*
1534 * Sanity check sequence number state.
1535 */
1536static void
1537ng_l2tp_seq_check(struct l2tp_seq *seq)
1538{
1539	const int self_unack = L2TP_SEQ_DIFF(seq->nr, seq->xack);
1540	const int peer_unack = L2TP_SEQ_DIFF(seq->ns, seq->rack);
1541	int i;
1542
1543#define CHECK(p)	KASSERT((p), ("%s: not: %s", __func__, #p))
1544
1545	CHECK(seq->wmax <= L2TP_MAX_XWIN);
1546	CHECK(seq->cwnd >= 1);
1547	CHECK(seq->cwnd <= seq->wmax);
1548	CHECK(seq->ssth >= 1);
1549	CHECK(seq->ssth <= seq->wmax);
1550	if (seq->cwnd < seq->ssth)
1551		CHECK(seq->acks == 0);
1552	else
1553		CHECK(seq->acks <= seq->cwnd);
1554	CHECK(self_unack >= 0);
1555	CHECK(peer_unack >= 0);
1556	CHECK(peer_unack <= seq->wmax);
1557	CHECK((self_unack == 0) ^ callout_active(&seq->xack_timer));
1558	CHECK((peer_unack == 0) ^ callout_active(&seq->rack_timer));
1559	for (i = 0; i < peer_unack; i++)
1560		CHECK(seq->xwin[i] != NULL);
1561	for ( ; i < seq->cwnd; i++)	    /* verify peer's recv window full */
1562		CHECK(seq->xwin[i] == NULL);
1563
1564#undef CHECK
1565}
1566#endif	/* INVARIANTS */
1567