ng_l2tp.c revision 131155
1238730Sdelphij
2294286Sdelphij/*
3238730Sdelphij * Copyright (c) 2001-2002 Packet Design, LLC.
4238730Sdelphij * All rights reserved.
5238730Sdelphij *
6238730Sdelphij * Subject to the following obligations and disclaimer of warranty,
7238730Sdelphij * use and redistribution of this software, in source or object code
8238730Sdelphij * forms, with or without modifications are expressly permitted by
960786Sps * Packet Design; provided, however, that:
1060786Sps *
1160786Sps *    (i)  Any and all reproductions of the source or object code
1260786Sps *         must include the copyright notice above and the following
1360786Sps *         disclaimer of warranties; and
1460786Sps *    (ii) No rights are granted, in any manner or form, to use
1560786Sps *         Packet Design trademarks, including the mark "PACKET DESIGN"
1660786Sps *         on advertising, endorsements, or otherwise except as such
1760786Sps *         appears in the above copyright notice or in the software.
1860786Sps *
1960786Sps * THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
2060786Sps * TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
2160786Sps * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
2260786Sps * THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
2360786Sps * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
2460786Sps * OR NON-INFRINGEMENT.  PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
2560786Sps * OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
2660786Sps * OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
2760786Sps * RELIABILITY OR OTHERWISE.  IN NO EVENT SHALL PACKET DESIGN BE
2860786Sps * LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
2960786Sps * OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
3060786Sps * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
3160786Sps * DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
3260786Sps * USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
3360786Sps * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3460786Sps * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3560786Sps * THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
3660786Sps * THE POSSIBILITY OF SUCH DAMAGE.
3760786Sps *
3860786Sps * Author: Archie Cobbs <archie@freebsd.org>
3960786Sps *
4060786Sps * $FreeBSD: head/sys/netgraph/ng_l2tp.c 131155 2004-06-26 22:24:16Z julian $
4160786Sps */
4260786Sps
4360786Sps/*
4460786Sps * L2TP netgraph node type.
4560786Sps *
4660786Sps * This node type implements the lower layer of the
4760786Sps * L2TP protocol as specified in RFC 2661.
4860786Sps */
4960786Sps
5060786Sps#include <sys/param.h>
5160786Sps#include <sys/systm.h>
5260786Sps#include <sys/kernel.h>
5360786Sps#include <sys/time.h>
5460786Sps#include <sys/conf.h>
5560786Sps#include <sys/mbuf.h>
5660786Sps#include <sys/malloc.h>
5760786Sps#include <sys/errno.h>
5860786Sps#include <sys/libkern.h>
5960786Sps
6060786Sps#include <netgraph/ng_message.h>
6160786Sps#include <netgraph/netgraph.h>
6260786Sps#include <netgraph/ng_parse.h>
6360786Sps#include <netgraph/ng_l2tp.h>
6460786Sps
6560786Sps#ifdef NG_SEPARATE_MALLOC
6660786SpsMALLOC_DEFINE(M_NETGRAPH_L2TP, "netgraph_l2tp", "netgraph l2tp node");
6760786Sps#else
6860786Sps#define M_NETGRAPH_L2TP M_NETGRAPH
6960786Sps#endif
7060786Sps
7160786Sps/* L2TP header format (first 2 bytes only) */
7260786Sps#define L2TP_HDR_CTRL		0x8000			/* control packet */
7360786Sps#define L2TP_HDR_LEN		0x4000			/* has length field */
7460786Sps#define L2TP_HDR_SEQ		0x0800			/* has ns, nr fields */
7560786Sps#define L2TP_HDR_OFF		0x0200			/* has offset field */
7660786Sps#define L2TP_HDR_PRIO		0x0100			/* give priority */
7760786Sps#define L2TP_HDR_VERS_MASK	0x000f			/* version field mask */
7860786Sps#define L2TP_HDR_VERSION	0x0002			/* version field */
7960786Sps
8060786Sps/* Bits that must be zero or one in first two bytes of header */
8160786Sps#define L2TP_CTRL_0BITS		0x030d			/* ctrl: must be 0 */
8260786Sps#define L2TP_CTRL_1BITS		0xc802			/* ctrl: must be 1 */
8360786Sps#define L2TP_DATA_0BITS		0x800d			/* data: must be 0 */
8460786Sps#define L2TP_DATA_1BITS		0x0002			/* data: must be 1 */
8560786Sps
8660786Sps/* Standard xmit ctrl and data header bits */
8760786Sps#define L2TP_CTRL_HDR		(L2TP_HDR_CTRL | L2TP_HDR_LEN \
8860786Sps				    | L2TP_HDR_SEQ | L2TP_HDR_VERSION)
8960786Sps#define L2TP_DATA_HDR		(L2TP_HDR_VERSION)	/* optional: len, seq */
9060786Sps
9160786Sps/* Some hard coded values */
9260786Sps#define L2TP_MAX_XWIN		16			/* my max xmit window */
9360786Sps#define L2TP_MAX_REXMIT		5			/* default max rexmit */
9460786Sps#define L2TP_MAX_REXMIT_TO	30			/* default rexmit to */
9560786Sps#define L2TP_DELAYED_ACK	((hz + 19) / 20)	/* delayed ack: 50 ms */
9660786Sps
9760786Sps/* Default data sequence number configuration for new sessions */
9860786Sps#define L2TP_CONTROL_DSEQ	1			/* we are the lns */
9960786Sps#define L2TP_ENABLE_DSEQ	1			/* enable data seq # */
10060786Sps
10160786Sps/* Compare sequence numbers using circular math */
10260786Sps#define L2TP_SEQ_DIFF(x, y)	((int)((int16_t)(x) - (int16_t)(y)))
10360786Sps
10460786Sps/*
10560786Sps * Sequence number state
10660786Sps *
10760786Sps * Invariants:
10860786Sps *    - If cwnd < ssth, we're doing slow start, otherwise congestion avoidance
10960786Sps *    - The number of unacknowledged xmit packets is (ns - rack) <= seq->wmax
11060786Sps *    - The first (ns - rack) mbuf's in xwin[] array are copies of these
11160786Sps *	unacknowledged packets; the remainder of xwin[] consists first of
11260786Sps *	zero or more further untransmitted packets in the transmit queue
11360786Sps *    - We try to keep the peer's receive window as full as possible.
11460786Sps *	Therefore, (i < cwnd && xwin[i] != NULL) implies (ns - rack) > i.
11560786Sps *    - rack_timer is running iff (ns - rack) > 0 (unack'd xmit'd pkts)
11660786Sps *    - If xack != nr, there are unacknowledged recv packet(s) (delayed ack)
11760786Sps *    - xack_timer is running iff xack != nr (unack'd rec'd pkts)
11860786Sps */
11960786Spsstruct l2tp_seq {
12060786Sps	u_int16_t		ns;		/* next xmit seq we send */
12160786Sps	u_int16_t		nr;		/* next recv seq we expect */
12260786Sps	u_int16_t		rack;		/* last 'nr' we rec'd */
12360786Sps	u_int16_t		xack;		/* last 'nr' we sent */
12460786Sps	u_int16_t		wmax;		/* peer's max recv window */
12560786Sps	u_int16_t		cwnd;		/* current congestion window */
12660786Sps	u_int16_t		ssth;		/* slow start threshold */
12760786Sps	u_int16_t		acks;		/* # consecutive acks rec'd */
12860786Sps	u_int16_t		rexmits;	/* # retransmits sent */
12960786Sps	u_int16_t		max_rexmits;	/* max # retransmits sent */
13060786Sps	u_int16_t		max_rexmit_to;	/* max retransmit timeout */
13160786Sps	struct callout		rack_timer;	/* retransmit timer */
13260786Sps	struct callout		xack_timer;	/* delayed ack timer */
13360786Sps	u_char			rack_timer_running;	/* xmit timer running */
13460786Sps	u_char			xack_timer_running;	/* ack timer running */
13560786Sps	struct mbuf		*xwin[L2TP_MAX_XWIN];	/* transmit window */
13660786Sps};
13760786Sps
13860786Sps/* Node private data */
13960786Spsstruct ng_l2tp_private {
14060786Sps	node_p			node;		/* back pointer to node */
14160786Sps	hook_p			ctrl;		/* hook to upper layers */
14260786Sps	hook_p			lower;		/* hook to lower layers */
14360786Sps	struct ng_l2tp_config	conf;		/* node configuration */
14460786Sps	struct ng_l2tp_stats	stats;		/* node statistics */
14560786Sps	struct l2tp_seq		seq;		/* ctrl sequence number state */
14660786Sps	ng_ID_t			ftarget;	/* failure message target */
14760786Sps};
14860786Spstypedef struct ng_l2tp_private *priv_p;
14960786Sps
15060786Sps/* Hook private data (data session hooks only) */
15160786Spsstruct ng_l2tp_hook_private {
15260786Sps	struct ng_l2tp_sess_config	conf;	/* hook/session config */
15360786Sps	u_int16_t			ns;	/* data ns sequence number */
15460786Sps	u_int16_t			nr;	/* data nr sequence number */
15560786Sps};
15660786Spstypedef struct ng_l2tp_hook_private *hookpriv_p;
15760786Sps
15860786Sps/* Netgraph node methods */
15960786Spsstatic ng_constructor_t	ng_l2tp_constructor;
16060786Spsstatic ng_rcvmsg_t	ng_l2tp_rcvmsg;
16160786Spsstatic ng_shutdown_t	ng_l2tp_shutdown;
16260786Spsstatic ng_newhook_t	ng_l2tp_newhook;
16360786Spsstatic ng_rcvdata_t	ng_l2tp_rcvdata;
16460786Spsstatic ng_disconnect_t	ng_l2tp_disconnect;
165242584Sdelphij
16660786Sps/* Internal functions */
16760786Spsstatic int	ng_l2tp_recv_lower(node_p node, item_p item);
16860786Spsstatic int	ng_l2tp_recv_ctrl(node_p node, item_p item);
16960786Spsstatic int	ng_l2tp_recv_data(node_p node, item_p item, hookpriv_p hpriv);
17060786Sps
17160786Spsstatic int	ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns);
17260786Sps
17360786Spsstatic void	ng_l2tp_seq_init(priv_p priv);
17460786Spsstatic int	ng_l2tp_seq_adjust(priv_p priv,
17560786Sps			const struct ng_l2tp_config *conf);
17660786Spsstatic void	ng_l2tp_seq_reset(priv_p priv);
17760786Spsstatic void	ng_l2tp_seq_failure(priv_p priv);
17860786Spsstatic void	ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr);
17960786Spsstatic int	ng_l2tp_seq_recv_ns(priv_p priv, u_int16_t ns);
18060786Spsstatic void	ng_l2tp_seq_xack_timeout(void *arg);
18160786Spsstatic void	ng_l2tp_seq_rack_timeout(void *arg);
18260786Sps
18360786Spsstatic ng_fn_eachhook	ng_l2tp_find_session;
18460786Spsstatic ng_fn_eachhook	ng_l2tp_reset_session;
18560786Sps
18660786Sps#ifdef INVARIANTS
18760786Spsstatic void	ng_l2tp_seq_check(struct l2tp_seq *seq);
18860786Sps#endif
18960786Sps
19060786Sps/* Parse type for struct ng_l2tp_config */
19160786Spsstatic const struct ng_parse_struct_field
19260786Sps	ng_l2tp_config_type_fields[] = NG_L2TP_CONFIG_TYPE_INFO;
19360786Spsstatic const struct ng_parse_type ng_l2tp_config_type = {
19460786Sps	&ng_parse_struct_type,
19560786Sps	&ng_l2tp_config_type_fields,
19660786Sps};
19760786Sps
19860786Sps/* Parse type for struct ng_l2tp_sess_config */
19960786Spsstatic const struct ng_parse_struct_field
20060786Sps	ng_l2tp_sess_config_type_fields[] = NG_L2TP_SESS_CONFIG_TYPE_INFO;
20160786Spsstatic const struct ng_parse_type ng_l2tp_sess_config_type = {
20260786Sps	&ng_parse_struct_type,
20360786Sps	&ng_l2tp_sess_config_type_fields,
20460786Sps};
20560786Sps
20660786Sps/* Parse type for struct ng_l2tp_stats */
20760786Spsstatic const struct ng_parse_struct_field
20860786Sps	ng_l2tp_stats_type_fields[] = NG_L2TP_STATS_TYPE_INFO;
20960786Spsstatic const struct ng_parse_type ng_l2tp_stats_type = {
21060786Sps	&ng_parse_struct_type,
21160786Sps	&ng_l2tp_stats_type_fields
21260786Sps};
21360786Sps
21460786Sps/* List of commands and how to convert arguments to/from ASCII */
21560786Spsstatic const struct ng_cmdlist ng_l2tp_cmdlist[] = {
21660786Sps	{
21760786Sps	  NGM_L2TP_COOKIE,
21860786Sps	  NGM_L2TP_SET_CONFIG,
21960786Sps	  "setconfig",
22060786Sps	  &ng_l2tp_config_type,
22160786Sps	  NULL
22260786Sps	},
22360786Sps	{
22460786Sps	  NGM_L2TP_COOKIE,
22560786Sps	  NGM_L2TP_GET_CONFIG,
22660786Sps	  "getconfig",
22760786Sps	  NULL,
22860786Sps	  &ng_l2tp_config_type
22960786Sps	},
23060786Sps	{
23160786Sps	  NGM_L2TP_COOKIE,
232	  NGM_L2TP_SET_SESS_CONFIG,
233	  "setsessconfig",
234	  &ng_l2tp_sess_config_type,
235	  NULL
236	},
237	{
238	  NGM_L2TP_COOKIE,
239	  NGM_L2TP_GET_SESS_CONFIG,
240	  "getsessconfig",
241	  &ng_parse_hint16_type,
242	  &ng_l2tp_sess_config_type
243	},
244	{
245	  NGM_L2TP_COOKIE,
246	  NGM_L2TP_GET_STATS,
247	  "getstats",
248	  NULL,
249	  &ng_l2tp_stats_type
250	},
251	{
252	  NGM_L2TP_COOKIE,
253	  NGM_L2TP_CLR_STATS,
254	  "clrstats",
255	  NULL,
256	  NULL
257	},
258	{
259	  NGM_L2TP_COOKIE,
260	  NGM_L2TP_GETCLR_STATS,
261	  "getclrstats",
262	  NULL,
263	  &ng_l2tp_stats_type
264	},
265	{
266	  NGM_L2TP_COOKIE,
267	  NGM_L2TP_ACK_FAILURE,
268	  "ackfailure",
269	  NULL,
270	  NULL
271	},
272	{ 0 }
273};
274
275/* Node type descriptor */
276static struct ng_type ng_l2tp_typestruct = {
277	.version =	NG_ABI_VERSION,
278	.name =		NG_L2TP_NODE_TYPE,
279	.constructor =	ng_l2tp_constructor,
280	.rcvmsg =	ng_l2tp_rcvmsg,
281	.shutdown =	ng_l2tp_shutdown,
282	.newhook =	ng_l2tp_newhook,
283	.rcvdata =	ng_l2tp_rcvdata,
284	.disconnect =	ng_l2tp_disconnect,
285	.cmdlist =	ng_l2tp_cmdlist,
286};
287NETGRAPH_INIT(l2tp, &ng_l2tp_typestruct);
288
289/* Sequence number state sanity checking */
290#ifdef INVARIANTS
291#define L2TP_SEQ_CHECK(seq)	ng_l2tp_seq_check(seq)
292#else
293#define L2TP_SEQ_CHECK(x)	do { } while (0)
294#endif
295
296/* memmove macro */
297#define memmove(d, s, l)	bcopy(s, d, l)
298
299/* Whether to use m_copypacket() or m_dup() */
300#define L2TP_COPY_MBUF		m_copypacket
301
302/************************************************************************
303			NETGRAPH NODE STUFF
304************************************************************************/
305
306/*
307 * Node type constructor
308 */
309static int
310ng_l2tp_constructor(node_p node)
311{
312	priv_p priv;
313
314	/* Allocate private structure */
315	MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH_L2TP, M_NOWAIT | M_ZERO);
316	if (priv == NULL)
317		return (ENOMEM);
318	NG_NODE_SET_PRIVATE(node, priv);
319	priv->node = node;
320
321	/* Apply a semi-reasonable default configuration */
322	priv->conf.peer_win = 1;
323	priv->conf.rexmit_max = L2TP_MAX_REXMIT;
324	priv->conf.rexmit_max_to = L2TP_MAX_REXMIT_TO;
325
326	/* Initialize sequence number state */
327	ng_l2tp_seq_init(priv);
328
329	/* Done */
330	return (0);
331}
332
333/*
334 * Give our OK for a hook to be added.
335 */
336static int
337ng_l2tp_newhook(node_p node, hook_p hook, const char *name)
338{
339	const priv_p priv = NG_NODE_PRIVATE(node);
340
341	/* Check hook name */
342	if (strcmp(name, NG_L2TP_HOOK_CTRL) == 0) {
343		if (priv->ctrl != NULL)
344			return (EISCONN);
345		priv->ctrl = hook;
346	} else if (strcmp(name, NG_L2TP_HOOK_LOWER) == 0) {
347		if (priv->lower != NULL)
348			return (EISCONN);
349		priv->lower = hook;
350	} else {
351		static const char hexdig[16] = "0123456789abcdef";
352		u_int16_t session_id;
353		hookpriv_p hpriv;
354		const char *hex;
355		int i;
356		int j;
357
358		/* Parse hook name to get session ID */
359		if (strncmp(name, NG_L2TP_HOOK_SESSION_P,
360		    sizeof(NG_L2TP_HOOK_SESSION_P) - 1) != 0)
361			return (EINVAL);
362		hex = name + sizeof(NG_L2TP_HOOK_SESSION_P) - 1;
363		for (session_id = i = 0; i < 4; i++) {
364			for (j = 0; j < 16 && hex[i] != hexdig[j]; j++);
365			if (j == 16)
366				return (EINVAL);
367			session_id = (session_id << 4) | j;
368		}
369		if (hex[i] != '\0')
370			return (EINVAL);
371
372		/* Create hook private structure */
373		MALLOC(hpriv, hookpriv_p,
374		    sizeof(*hpriv), M_NETGRAPH_L2TP, M_NOWAIT | M_ZERO);
375		if (hpriv == NULL)
376			return (ENOMEM);
377		hpriv->conf.session_id = htons(session_id);
378		hpriv->conf.control_dseq = L2TP_CONTROL_DSEQ;
379		hpriv->conf.enable_dseq = L2TP_ENABLE_DSEQ;
380		NG_HOOK_SET_PRIVATE(hook, hpriv);
381	}
382
383	/* Done */
384	return (0);
385}
386
387/*
388 * Receive a control message.
389 */
390static int
391ng_l2tp_rcvmsg(node_p node, item_p item, hook_p lasthook)
392{
393	const priv_p priv = NG_NODE_PRIVATE(node);
394	struct ng_mesg *resp = NULL;
395	struct ng_mesg *msg;
396	int error = 0;
397
398	NGI_GET_MSG(item, msg);
399	switch (msg->header.typecookie) {
400	case NGM_L2TP_COOKIE:
401		switch (msg->header.cmd) {
402		case NGM_L2TP_SET_CONFIG:
403		    {
404			struct ng_l2tp_config *const conf =
405				(struct ng_l2tp_config *)msg->data;
406
407			/* Check for invalid or illegal config */
408			if (msg->header.arglen != sizeof(*conf)) {
409				error = EINVAL;
410				break;
411			}
412			conf->enabled = !!conf->enabled;
413			conf->match_id = !!conf->match_id;
414			conf->tunnel_id = htons(conf->tunnel_id);
415			conf->peer_id = htons(conf->peer_id);
416			if (priv->conf.enabled
417			    && ((priv->conf.tunnel_id != 0
418			       && conf->tunnel_id != priv->conf.tunnel_id)
419			      || ((priv->conf.peer_id != 0
420			       && conf->peer_id != priv->conf.peer_id)))) {
421				error = EBUSY;
422				break;
423			}
424
425			/* Save calling node as failure target */
426			priv->ftarget = NGI_RETADDR(item);
427
428			/* Adjust sequence number state */
429			if ((error = ng_l2tp_seq_adjust(priv, conf)) != 0)
430				break;
431
432			/* Update node's config */
433			priv->conf = *conf;
434			break;
435		    }
436		case NGM_L2TP_GET_CONFIG:
437		    {
438			struct ng_l2tp_config *conf;
439
440			NG_MKRESPONSE(resp, msg, sizeof(*conf), M_NOWAIT);
441			if (resp == NULL) {
442				error = ENOMEM;
443				break;
444			}
445			conf = (struct ng_l2tp_config *)resp->data;
446			*conf = priv->conf;
447
448			/* Put ID's in host order */
449			conf->tunnel_id = ntohs(conf->tunnel_id);
450			conf->peer_id = ntohs(conf->peer_id);
451			break;
452		    }
453		case NGM_L2TP_SET_SESS_CONFIG:
454		    {
455			struct ng_l2tp_sess_config *const conf =
456			    (struct ng_l2tp_sess_config *)msg->data;
457			hookpriv_p hpriv;
458			hook_p hook;
459
460			/* Check for invalid or illegal config */
461			if (msg->header.arglen != sizeof(*conf)) {
462				error = EINVAL;
463				break;
464			}
465
466			/* Put ID's in network order */
467			conf->session_id = htons(conf->session_id);
468			conf->peer_id = htons(conf->peer_id);
469
470			/* Find matching hook */
471			NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
472			    (void *)(uintptr_t)conf->session_id, hook);
473			if (hook == NULL) {
474				error = ENOENT;
475				break;
476			}
477			hpriv = NG_HOOK_PRIVATE(hook);
478
479			/* Update hook's config */
480			hpriv->conf = *conf;
481			break;
482		    }
483		case NGM_L2TP_GET_SESS_CONFIG:
484		    {
485			struct ng_l2tp_sess_config *conf;
486			u_int16_t session_id;
487			hookpriv_p hpriv;
488			hook_p hook;
489
490			/* Get session ID */
491			if (msg->header.arglen != sizeof(session_id)) {
492				error = EINVAL;
493				break;
494			}
495			memcpy(&session_id, msg->data, 2);
496			session_id = htons(session_id);
497
498			/* Find matching hook */
499			NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
500			    (void *)(uintptr_t)session_id, hook);
501			if (hook == NULL) {
502				error = ENOENT;
503				break;
504			}
505			hpriv = NG_HOOK_PRIVATE(hook);
506
507			/* Send response */
508			NG_MKRESPONSE(resp, msg, sizeof(hpriv->conf), M_NOWAIT);
509			if (resp == NULL) {
510				error = ENOMEM;
511				break;
512			}
513			conf = (struct ng_l2tp_sess_config *)resp->data;
514			*conf = hpriv->conf;
515
516			/* Put ID's in host order */
517			conf->session_id = ntohs(conf->session_id);
518			conf->peer_id = ntohs(conf->peer_id);
519			break;
520		    }
521		case NGM_L2TP_GET_STATS:
522		case NGM_L2TP_CLR_STATS:
523		case NGM_L2TP_GETCLR_STATS:
524		    {
525			if (msg->header.cmd != NGM_L2TP_CLR_STATS) {
526				NG_MKRESPONSE(resp, msg,
527				    sizeof(priv->stats), M_NOWAIT);
528				if (resp == NULL) {
529					error = ENOMEM;
530					break;
531				}
532				memcpy(resp->data,
533				    &priv->stats, sizeof(priv->stats));
534			}
535			if (msg->header.cmd != NGM_L2TP_GET_STATS)
536				memset(&priv->stats, 0, sizeof(priv->stats));
537			break;
538		    }
539		default:
540			error = EINVAL;
541			break;
542		}
543		break;
544	default:
545		error = EINVAL;
546		break;
547	}
548
549	/* Done */
550	NG_RESPOND_MSG(error, node, item, resp);
551	NG_FREE_MSG(msg);
552	return (error);
553}
554
555/*
556 * Receive incoming data on a hook.
557 */
558static int
559ng_l2tp_rcvdata(hook_p hook, item_p item)
560{
561	const node_p node = NG_HOOK_NODE(hook);
562	const priv_p priv = NG_NODE_PRIVATE(node);
563	int error;
564
565	/* Sanity check */
566	L2TP_SEQ_CHECK(&priv->seq);
567
568	/* If not configured, reject */
569	if (!priv->conf.enabled) {
570		NG_FREE_ITEM(item);
571		return (ENXIO);
572	}
573
574	/* Handle incoming frame from below */
575	if (hook == priv->lower) {
576		error = ng_l2tp_recv_lower(node, item);
577		goto done;
578	}
579
580	/* Handle outgoing control frame */
581	if (hook == priv->ctrl) {
582		error = ng_l2tp_recv_ctrl(node, item);
583		goto done;
584	}
585
586	/* Handle outgoing data frame */
587	error = ng_l2tp_recv_data(node, item, NG_HOOK_PRIVATE(hook));
588
589done:
590	/* Done */
591	L2TP_SEQ_CHECK(&priv->seq);
592	return (error);
593}
594
595/*
596 * Destroy node
597 */
598static int
599ng_l2tp_shutdown(node_p node)
600{
601	const priv_p priv = NG_NODE_PRIVATE(node);
602	struct l2tp_seq *const seq = &priv->seq;
603
604	/* Sanity check */
605	L2TP_SEQ_CHECK(seq);
606
607	/* Reset sequence number state */
608	ng_l2tp_seq_reset(priv);
609
610	/* Free private data if neither timer is running */
611	if (!seq->rack_timer_running && !seq->xack_timer_running) {
612		FREE(priv, M_NETGRAPH_L2TP);
613		NG_NODE_SET_PRIVATE(node, NULL);
614	}
615
616	/* Unref node */
617	NG_NODE_UNREF(node);
618	return (0);
619}
620
621/*
622 * Hook disconnection
623 */
624static int
625ng_l2tp_disconnect(hook_p hook)
626{
627	const node_p node = NG_HOOK_NODE(hook);
628	const priv_p priv = NG_NODE_PRIVATE(node);
629
630	/* Zero out hook pointer */
631	if (hook == priv->ctrl)
632		priv->ctrl = NULL;
633	else if (hook == priv->lower)
634		priv->lower = NULL;
635	else {
636		FREE(NG_HOOK_PRIVATE(hook), M_NETGRAPH_L2TP);
637		NG_HOOK_SET_PRIVATE(hook, NULL);
638	}
639
640	/* Go away if no longer connected to anything */
641	if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node))
642		ng_rmnode_self(node);
643	return (0);
644}
645
646/*************************************************************************
647			INTERNAL FUNCTIONS
648*************************************************************************/
649
650/*
651 * Find the hook with a given session ID.
652 */
653static int
654ng_l2tp_find_session(hook_p hook, void *arg)
655{
656	const hookpriv_p hpriv = NG_HOOK_PRIVATE(hook);
657	const u_int16_t sid = (u_int16_t)(uintptr_t)arg;
658
659	if (hpriv == NULL || hpriv->conf.session_id != sid)
660		return (-1);
661	return (0);
662}
663
664/*
665 * Reset a hook's session state.
666 */
667static int
668ng_l2tp_reset_session(hook_p hook, void *arg)
669{
670	const hookpriv_p hpriv = NG_HOOK_PRIVATE(hook);
671
672	if (hpriv != NULL) {
673		hpriv->conf.control_dseq = 0;
674		hpriv->conf.enable_dseq = 0;
675		hpriv->nr = 0;
676		hpriv->ns = 0;
677	}
678	return (-1);
679}
680
681/*
682 * Handle an incoming frame from below.
683 */
684static int
685ng_l2tp_recv_lower(node_p node, item_p item)
686{
687	static const u_int16_t req_bits[2][2] = {
688		{ L2TP_DATA_0BITS, L2TP_DATA_1BITS },
689		{ L2TP_CTRL_0BITS, L2TP_CTRL_1BITS },
690	};
691	const priv_p priv = NG_NODE_PRIVATE(node);
692	hookpriv_p hpriv = NULL;
693	hook_p hook = NULL;
694	u_int16_t ids[2];
695	struct mbuf *m;
696	u_int16_t hdr;
697	u_int16_t ns;
698	u_int16_t nr;
699	int is_ctrl;
700	int error;
701	int len;
702
703	/* Grab mbuf */
704	NGI_GET_M(item, m);
705
706	/* Update stats */
707	priv->stats.recvPackets++;
708	priv->stats.recvOctets += m->m_pkthdr.len;
709
710	/* Get initial header */
711	if (m->m_pkthdr.len < 6) {
712		priv->stats.recvRunts++;
713		NG_FREE_ITEM(item);
714		NG_FREE_M(m);
715		return (EINVAL);
716	}
717	if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
718		priv->stats.memoryFailures++;
719		NG_FREE_ITEM(item);
720		return (EINVAL);
721	}
722	hdr = ntohs(*mtod(m, u_int16_t *));
723	m_adj(m, 2);
724
725	/* Check required header bits and minimum length */
726	is_ctrl = (hdr & L2TP_HDR_CTRL) != 0;
727	if ((hdr & req_bits[is_ctrl][0]) != 0
728	    || (~hdr & req_bits[is_ctrl][1]) != 0) {
729		priv->stats.recvInvalid++;
730		NG_FREE_ITEM(item);
731		NG_FREE_M(m);
732		return (EINVAL);
733	}
734	if (m->m_pkthdr.len < 4				/* tunnel, session id */
735	    + (2 * ((hdr & L2TP_HDR_LEN) != 0))		/* length field */
736	    + (4 * ((hdr & L2TP_HDR_SEQ) != 0))		/* seq # fields */
737	    + (2 * ((hdr & L2TP_HDR_OFF) != 0))) {	/* offset field */
738		priv->stats.recvRunts++;
739		NG_FREE_ITEM(item);
740		NG_FREE_M(m);
741		return (EINVAL);
742	}
743
744	/* Get and validate length field if present */
745	if ((hdr & L2TP_HDR_LEN) != 0) {
746		if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
747			priv->stats.memoryFailures++;
748			NG_FREE_ITEM(item);
749			return (EINVAL);
750		}
751		len = (u_int16_t)ntohs(*mtod(m, u_int16_t *)) - 4;
752		m_adj(m, 2);
753		if (len < 0 || len > m->m_pkthdr.len) {
754			priv->stats.recvInvalid++;
755			NG_FREE_ITEM(item);
756			NG_FREE_M(m);
757			return (EINVAL);
758		}
759		if (len < m->m_pkthdr.len)		/* trim extra bytes */
760			m_adj(m, -(m->m_pkthdr.len - len));
761	}
762
763	/* Get tunnel ID and session ID */
764	if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
765		priv->stats.memoryFailures++;
766		NG_FREE_ITEM(item);
767		return (EINVAL);
768	}
769	memcpy(ids, mtod(m, u_int16_t *), 4);
770	m_adj(m, 4);
771
772	/* Check tunnel ID */
773	if (ids[0] != priv->conf.tunnel_id
774	    && (priv->conf.match_id || ids[0] != 0)) {
775		priv->stats.recvWrongTunnel++;
776		NG_FREE_ITEM(item);
777		NG_FREE_M(m);
778		return (EADDRNOTAVAIL);
779	}
780
781	/* Check session ID (for data packets only) */
782	if ((hdr & L2TP_HDR_CTRL) == 0) {
783		NG_NODE_FOREACH_HOOK(node, ng_l2tp_find_session,
784		    (void *)(uintptr_t)ids[1], hook);
785		if (hook == NULL) {
786			priv->stats.recvUnknownSID++;
787			NG_FREE_ITEM(item);
788			NG_FREE_M(m);
789			return (ENOTCONN);
790		}
791		hpriv = NG_HOOK_PRIVATE(hook);
792	}
793
794	/* Get Ns, Nr fields if present */
795	if ((hdr & L2TP_HDR_SEQ) != 0) {
796		if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) {
797			priv->stats.memoryFailures++;
798			NG_FREE_ITEM(item);
799			return (EINVAL);
800		}
801		memcpy(&ns, &mtod(m, u_int16_t *)[0], 2);
802		ns = ntohs(ns);
803		memcpy(&nr, &mtod(m, u_int16_t *)[1], 2);
804		nr = ntohs(nr);
805		m_adj(m, 4);
806	}
807
808	/* Strip offset padding if present */
809	if ((hdr & L2TP_HDR_OFF) != 0) {
810		u_int16_t offset;
811
812		/* Get length of offset padding */
813		if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
814			priv->stats.memoryFailures++;
815			NG_FREE_ITEM(item);
816			return (EINVAL);
817		}
818		memcpy(&offset, mtod(m, u_int16_t *), 2);
819		offset = ntohs(offset);
820
821		/* Trim offset padding */
822		if (offset <= 2 || offset > m->m_pkthdr.len) {
823			priv->stats.recvInvalid++;
824			NG_FREE_ITEM(item);
825			NG_FREE_M(m);
826			return (EINVAL);
827		}
828		m_adj(m, offset);
829	}
830
831	/* Handle control packets */
832	if ((hdr & L2TP_HDR_CTRL) != 0) {
833
834		/* Handle receive ack sequence number Nr */
835		ng_l2tp_seq_recv_nr(priv, nr);
836
837		/* Discard ZLB packets */
838		if (m->m_pkthdr.len == 0) {
839			priv->stats.recvZLBs++;
840			NG_FREE_ITEM(item);
841			NG_FREE_M(m);
842			return (0);
843		}
844
845		/*
846		 * Prepend session ID to packet here: we don't want to accept
847		 * the send sequence number Ns if we have to drop the packet
848		 * later because of a memory error, because then the upper
849		 * layer would never get the packet.
850		 */
851		M_PREPEND(m, 2, M_DONTWAIT);
852		if (m == NULL) {
853			priv->stats.memoryFailures++;
854			NG_FREE_ITEM(item);
855			return (ENOBUFS);
856		}
857		memcpy(mtod(m, u_int16_t *), &ids[1], 2);
858
859		/* Now handle send sequence number */
860		if (ng_l2tp_seq_recv_ns(priv, ns) == -1) {
861			NG_FREE_ITEM(item);
862			NG_FREE_M(m);
863			return (0);
864		}
865
866		/* Deliver packet to upper layers */
867		NG_FWD_NEW_DATA(error, item, priv->ctrl, m);
868		return (error);
869	}
870
871	/* Follow peer's lead in data sequencing, if configured to do so */
872	if (!hpriv->conf.control_dseq)
873		hpriv->conf.enable_dseq = ((hdr & L2TP_HDR_SEQ) != 0);
874
875	/* Handle data sequence numbers if present and enabled */
876	if ((hdr & L2TP_HDR_SEQ) != 0) {
877		if (hpriv->conf.enable_dseq
878		    && L2TP_SEQ_DIFF(ns, hpriv->nr) < 0) {
879			NG_FREE_ITEM(item);	/* duplicate or out of order */
880			NG_FREE_M(m);
881			priv->stats.recvDataDrops++;
882			return (0);
883		}
884		hpriv->nr = ns + 1;
885	}
886
887	/* Drop empty data packets */
888	if (m->m_pkthdr.len == 0) {
889		NG_FREE_ITEM(item);
890		NG_FREE_M(m);
891		return (0);
892	}
893
894	/* Deliver data */
895	NG_FWD_NEW_DATA(error, item, hook, m);
896	return (error);
897}
898
899/*
900 * Handle an outgoing control frame.
901 */
902static int
903ng_l2tp_recv_ctrl(node_p node, item_p item)
904{
905	const priv_p priv = NG_NODE_PRIVATE(node);
906	struct l2tp_seq *const seq = &priv->seq;
907	struct mbuf *m;
908	int i;
909
910	/* Grab mbuf and discard other stuff XXX */
911	NGI_GET_M(item, m);
912	NG_FREE_ITEM(item);
913
914	/* Packet should have session ID prepended */
915	if (m->m_pkthdr.len < 2) {
916		priv->stats.xmitInvalid++;
917		m_freem(m);
918		return (EINVAL);
919	}
920
921	/* Check max length */
922	if (m->m_pkthdr.len >= 0x10000 - 14) {
923		priv->stats.xmitTooBig++;
924		m_freem(m);
925		return (EOVERFLOW);
926	}
927
928	/* Find next empty slot in transmit queue */
929	for (i = 0; i < L2TP_MAX_XWIN && seq->xwin[i] != NULL; i++);
930	if (i == L2TP_MAX_XWIN) {
931		priv->stats.xmitDrops++;
932		m_freem(m);
933		return (ENOBUFS);
934	}
935	seq->xwin[i] = m;
936
937	/* Sanity check receive ack timer state */
938	KASSERT((i == 0) ^ seq->rack_timer_running,
939	    ("%s: xwin %d full but rack timer %srunning",
940	    __FUNCTION__, i, seq->rack_timer_running ? "" : "not "));
941
942	/* If peer's receive window is already full, nothing else to do */
943	if (i >= seq->cwnd)
944		return (0);
945
946	/* Start retransmit timer if not already running */
947	if (!seq->rack_timer_running) {
948		callout_reset(&seq->rack_timer,
949		    hz, ng_l2tp_seq_rack_timeout, node);
950		seq->rack_timer_running = 1;
951		NG_NODE_REF(node);
952	}
953
954	/* Copy packet */
955	if ((m = L2TP_COPY_MBUF(seq->xwin[i], M_DONTWAIT)) == NULL) {
956		priv->stats.memoryFailures++;
957		return (ENOBUFS);
958	}
959
960	/* Send packet and increment xmit sequence number */
961	return (ng_l2tp_xmit_ctrl(priv, m, seq->ns++));
962}
963
964/*
965 * Handle an outgoing data frame.
966 */
967static int
968ng_l2tp_recv_data(node_p node, item_p item, hookpriv_p hpriv)
969{
970	const priv_p priv = NG_NODE_PRIVATE(node);
971	struct mbuf *m;
972	u_int16_t hdr;
973	int error;
974	int i = 1;
975
976	/* Get mbuf */
977	NGI_GET_M(item, m);
978
979	/* Check max length */
980	if (m->m_pkthdr.len >= 0x10000 - 12) {
981		priv->stats.xmitDataTooBig++;
982		NG_FREE_ITEM(item);
983		NG_FREE_M(m);
984		return (EOVERFLOW);
985	}
986
987	/* Prepend L2TP header */
988	M_PREPEND(m, 6
989	    + (2 * (hpriv->conf.include_length != 0))
990	    + (4 * (hpriv->conf.enable_dseq != 0)),
991	    M_DONTWAIT);
992	if (m == NULL) {
993		priv->stats.memoryFailures++;
994		NG_FREE_ITEM(item);
995		return (ENOBUFS);
996	}
997	hdr = L2TP_DATA_HDR;
998	if (hpriv->conf.include_length) {
999		hdr |= L2TP_HDR_LEN;
1000		mtod(m, u_int16_t *)[i++] = htons(m->m_pkthdr.len);
1001	}
1002	mtod(m, u_int16_t *)[i++] = priv->conf.peer_id;
1003	mtod(m, u_int16_t *)[i++] = hpriv->conf.peer_id;
1004	if (hpriv->conf.enable_dseq) {
1005		hdr |= L2TP_HDR_SEQ;
1006		mtod(m, u_int16_t *)[i++] = htons(hpriv->ns);
1007		mtod(m, u_int16_t *)[i++] = htons(hpriv->nr);
1008		hpriv->ns++;
1009	}
1010	mtod(m, u_int16_t *)[0] = htons(hdr);
1011
1012	/* Send packet */
1013	NG_FWD_NEW_DATA(error, item, priv->lower, m);
1014	return (error);
1015}
1016
1017/*
1018 * Send a message to our controlling node that we've failed.
1019 */
1020static void
1021ng_l2tp_seq_failure(priv_p priv)
1022{
1023	struct ng_mesg *msg;
1024	int error;
1025
1026	NG_MKMESSAGE(msg, NGM_L2TP_COOKIE, NGM_L2TP_ACK_FAILURE, 0, M_NOWAIT);
1027	if (msg == NULL)
1028		return;
1029	NG_SEND_MSG_ID(error, priv->node, msg, priv->ftarget, 0);
1030}
1031
1032/************************************************************************
1033			SEQUENCE NUMBER HANDLING
1034************************************************************************/
1035
1036/*
1037 * Initialize sequence number state.
1038 */
1039static void
1040ng_l2tp_seq_init(priv_p priv)
1041{
1042	struct l2tp_seq *const seq = &priv->seq;
1043
1044	KASSERT(priv->conf.peer_win >= 1,
1045	    ("%s: peer_win is zero", __FUNCTION__));
1046	memset(seq, 0, sizeof(*seq));
1047	seq->cwnd = 1;
1048	seq->wmax = priv->conf.peer_win;
1049	if (seq->wmax > L2TP_MAX_XWIN)
1050		seq->wmax = L2TP_MAX_XWIN;
1051	seq->ssth = seq->wmax;
1052	seq->max_rexmits = priv->conf.rexmit_max;
1053	seq->max_rexmit_to = priv->conf.rexmit_max_to;
1054	callout_init(&seq->rack_timer, 0);
1055	callout_init(&seq->xack_timer, 0);
1056	L2TP_SEQ_CHECK(seq);
1057}
1058
1059/*
1060 * Adjust sequence number state accordingly after reconfiguration.
1061 */
1062static int
1063ng_l2tp_seq_adjust(priv_p priv, const struct ng_l2tp_config *conf)
1064{
1065	struct l2tp_seq *const seq = &priv->seq;
1066	u_int16_t new_wmax;
1067
1068	/* If disabling node, reset state sequence number */
1069	if (!conf->enabled) {
1070		ng_l2tp_seq_reset(priv);
1071		return (0);
1072	}
1073
1074	/* Adjust peer's max recv window; it can only increase */
1075	new_wmax = conf->peer_win;
1076	if (new_wmax > L2TP_MAX_XWIN)
1077		new_wmax = L2TP_MAX_XWIN;
1078	if (new_wmax == 0)
1079		return (EINVAL);
1080	if (new_wmax < seq->wmax)
1081		return (EBUSY);
1082	seq->wmax = new_wmax;
1083
1084	/* Update retransmit parameters */
1085	seq->max_rexmits = conf->rexmit_max;
1086	seq->max_rexmit_to = conf->rexmit_max_to;
1087
1088	/* Done */
1089	return (0);
1090}
1091
1092/*
1093 * Reset sequence number state.
1094 */
1095static void
1096ng_l2tp_seq_reset(priv_p priv)
1097{
1098	struct l2tp_seq *const seq = &priv->seq;
1099	hook_p hook;
1100	int i;
1101
1102	/* Sanity check */
1103	L2TP_SEQ_CHECK(seq);
1104
1105	/* Stop timers */
1106	if (seq->rack_timer_running && callout_stop(&seq->rack_timer) == 1) {
1107		seq->rack_timer_running = 0;
1108		NG_NODE_UNREF(priv->node);
1109	}
1110	if (seq->xack_timer_running && callout_stop(&seq->xack_timer) == 1) {
1111		seq->xack_timer_running = 0;
1112		NG_NODE_UNREF(priv->node);
1113	}
1114
1115	/* Free retransmit queue */
1116	for (i = 0; i < L2TP_MAX_XWIN; i++) {
1117		if (seq->xwin[i] == NULL)
1118			break;
1119		m_freem(seq->xwin[i]);
1120	}
1121
1122	/* Reset session hooks' sequence number states */
1123	NG_NODE_FOREACH_HOOK(priv->node, ng_l2tp_reset_session, NULL, hook);
1124
1125	/* Reset node's sequence number state */
1126	memset(seq, 0, sizeof(*seq));
1127	seq->cwnd = 1;
1128	seq->wmax = L2TP_MAX_XWIN;
1129	seq->ssth = seq->wmax;
1130
1131	/* Done */
1132	L2TP_SEQ_CHECK(seq);
1133}
1134
1135/*
1136 * Handle receipt of an acknowledgement value (Nr) from peer.
1137 */
1138static void
1139ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr)
1140{
1141	struct l2tp_seq *const seq = &priv->seq;
1142	struct mbuf *m;
1143	int nack;
1144	int i;
1145
1146	/* Verify peer's ACK is in range */
1147	if ((nack = L2TP_SEQ_DIFF(nr, seq->rack)) <= 0)
1148		return;				/* duplicate ack */
1149	if (L2TP_SEQ_DIFF(nr, seq->ns) > 0) {
1150		priv->stats.recvBadAcks++;	/* ack for packet not sent */
1151		return;
1152	}
1153	KASSERT(nack <= L2TP_MAX_XWIN,
1154	    ("%s: nack=%d > %d", __FUNCTION__, nack, L2TP_MAX_XWIN));
1155
1156	/* Update receive ack stats */
1157	seq->rack = nr;
1158	seq->rexmits = 0;
1159
1160	/* Free acknowledged packets and shift up packets in the xmit queue */
1161	for (i = 0; i < nack; i++)
1162		m_freem(seq->xwin[i]);
1163	memmove(seq->xwin, seq->xwin + nack,
1164	    (L2TP_MAX_XWIN - nack) * sizeof(*seq->xwin));
1165	memset(seq->xwin + (L2TP_MAX_XWIN - nack), 0,
1166	    nack * sizeof(*seq->xwin));
1167
1168	/*
1169	 * Do slow-start/congestion avoidance windowing algorithm described
1170	 * in RFC 2661, Appendix A. Here we handle a multiple ACK as if each
1171	 * ACK had arrived separately.
1172	 */
1173	if (seq->cwnd < seq->wmax) {
1174
1175		/* Handle slow start phase */
1176		if (seq->cwnd < seq->ssth) {
1177			seq->cwnd += nack;
1178			nack = 0;
1179			if (seq->cwnd > seq->ssth) {	/* into cg.av. phase */
1180				nack = seq->cwnd - seq->ssth;
1181				seq->cwnd = seq->ssth;
1182			}
1183		}
1184
1185		/* Handle congestion avoidance phase */
1186		if (seq->cwnd >= seq->ssth) {
1187			seq->acks += nack;
1188			while (seq->acks >= seq->cwnd) {
1189				seq->acks -= seq->cwnd;
1190				if (seq->cwnd < seq->wmax)
1191					seq->cwnd++;
1192			}
1193		}
1194	}
1195
1196	/* Stop xmit timer */
1197	if (seq->rack_timer_running && callout_stop(&seq->rack_timer) == 1) {
1198		seq->rack_timer_running = 0;
1199		NG_NODE_UNREF(priv->node);
1200	}
1201
1202	/* If transmit queue is empty, we're done for now */
1203	if (seq->xwin[0] == NULL)
1204		return;
1205
1206	/* Start restransmit timer again */
1207	callout_reset(&seq->rack_timer,
1208	    hz, ng_l2tp_seq_rack_timeout, priv->node);
1209	seq->rack_timer_running = 1;
1210	NG_NODE_REF(priv->node);
1211
1212	/*
1213	 * Send more packets, trying to keep peer's receive window full.
1214	 * If there is a memory error, pretend packet was sent, as it
1215	 * will get retransmitted later anyway.
1216	 */
1217	while ((i = L2TP_SEQ_DIFF(seq->ns, seq->rack)) < seq->cwnd
1218	    && seq->xwin[i] != NULL) {
1219		if ((m = L2TP_COPY_MBUF(seq->xwin[i], M_DONTWAIT)) == NULL)
1220			priv->stats.memoryFailures++;
1221		else
1222			ng_l2tp_xmit_ctrl(priv, m, seq->ns);
1223		seq->ns++;
1224	}
1225}
1226
1227/*
1228 * Handle receipt of a sequence number value (Ns) from peer.
1229 * We make no attempt to re-order out of order packets.
1230 *
1231 * This function should only be called for non-ZLB packets.
1232 *
1233 * Returns:
1234 *	 0	Accept packet
1235 *	-1	Drop packet
1236 */
1237static int
1238ng_l2tp_seq_recv_ns(priv_p priv, u_int16_t ns)
1239{
1240	struct l2tp_seq *const seq = &priv->seq;
1241
1242	/* If not what we expect, drop packet and send an immediate ZLB ack */
1243	if (ns != seq->nr) {
1244		if (L2TP_SEQ_DIFF(ns, seq->nr) < 0)
1245			priv->stats.recvDuplicates++;
1246		else
1247			priv->stats.recvOutOfOrder++;
1248		ng_l2tp_xmit_ctrl(priv, NULL, seq->ns);
1249		return (-1);
1250	}
1251
1252	/* Update recv sequence number */
1253	seq->nr++;
1254
1255	/* Start receive ack timer, if not already running */
1256	if (!seq->xack_timer_running) {
1257		callout_reset(&seq->xack_timer,
1258		    L2TP_DELAYED_ACK, ng_l2tp_seq_xack_timeout, priv->node);
1259		seq->xack_timer_running = 1;
1260		NG_NODE_REF(priv->node);
1261	}
1262
1263	/* Accept packet */
1264	return (0);
1265}
1266
1267/*
1268 * Handle an ack timeout. We have an outstanding ack that we
1269 * were hoping to piggy-back, but haven't, so send a ZLB.
1270 */
1271static void
1272ng_l2tp_seq_xack_timeout(void *arg)
1273{
1274	const node_p node = arg;
1275	const priv_p priv = NG_NODE_PRIVATE(node);
1276	struct l2tp_seq *const seq = &priv->seq;
1277	int s;
1278
1279	/* Check if node is going away */
1280	s = splnet();
1281	if (NG_NODE_NOT_VALID(node)) {
1282		seq->xack_timer_running = 0;
1283		if (!seq->rack_timer_running) {
1284			FREE(priv, M_NETGRAPH_L2TP);
1285			NG_NODE_SET_PRIVATE(node, NULL);
1286		}
1287		NG_NODE_UNREF(node);
1288		splx(s);
1289		return;
1290	}
1291
1292	/* Sanity check */
1293	L2TP_SEQ_CHECK(seq);
1294
1295	/* If ack is still outstanding, send a ZLB */
1296	if (seq->xack != seq->nr)
1297		ng_l2tp_xmit_ctrl(priv, NULL, seq->ns);
1298
1299	/* Done */
1300	seq->xack_timer_running = 0;
1301	NG_NODE_UNREF(node);
1302	L2TP_SEQ_CHECK(seq);
1303	splx(s);
1304}
1305
1306/*
1307 * Handle a transmit timeout. The peer has failed to respond
1308 * with an ack for our packet, so retransmit it.
1309 */
1310static void
1311ng_l2tp_seq_rack_timeout(void *arg)
1312{
1313	const node_p node = arg;
1314	const priv_p priv = NG_NODE_PRIVATE(node);
1315	struct l2tp_seq *const seq = &priv->seq;
1316	struct mbuf *m;
1317	u_int delay;
1318	int s;
1319
1320	/* Check if node is going away */
1321	s = splnet();
1322	if (NG_NODE_NOT_VALID(node)) {
1323		seq->rack_timer_running = 0;
1324		if (!seq->xack_timer_running) {
1325			FREE(priv, M_NETGRAPH_L2TP);
1326			NG_NODE_SET_PRIVATE(node, NULL);
1327		}
1328		NG_NODE_UNREF(node);
1329		splx(s);
1330		return;
1331	}
1332
1333	/* Sanity check */
1334	L2TP_SEQ_CHECK(seq);
1335
1336	/* Make sure peer's ack is still outstanding before doing anything */
1337	if (seq->rack == seq->ns) {
1338		seq->rack_timer_running = 0;
1339		NG_NODE_UNREF(node);
1340		goto done;
1341	}
1342	priv->stats.xmitRetransmits++;
1343
1344	/* Have we reached the retransmit limit? If so, notify owner. */
1345	if (seq->rexmits++ >= seq->max_rexmits)
1346		ng_l2tp_seq_failure(priv);
1347
1348	/* Restart timer, this time with an increased delay */
1349	delay = (seq->rexmits > 12) ? (1 << 12) : (1 << seq->rexmits);
1350	if (delay > seq->max_rexmit_to)
1351		delay = seq->max_rexmit_to;
1352	callout_reset(&seq->rack_timer,
1353	    hz * delay, ng_l2tp_seq_rack_timeout, node);
1354
1355	/* Do slow-start/congestion algorithm windowing algorithm */
1356	seq->ssth = (seq->cwnd + 1) / 2;
1357	seq->cwnd = 1;
1358	seq->acks = 0;
1359
1360	/* Retransmit oldest unack'd packet */
1361	if ((m = L2TP_COPY_MBUF(seq->xwin[0], M_DONTWAIT)) == NULL)
1362		priv->stats.memoryFailures++;
1363	else
1364		ng_l2tp_xmit_ctrl(priv, m, seq->rack);
1365
1366done:
1367	/* Done */
1368	L2TP_SEQ_CHECK(seq);
1369	splx(s);
1370}
1371
1372/*
1373 * Transmit a control stream packet, payload optional.
1374 * The transmit sequence number is not incremented.
1375 */
1376static int
1377ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns)
1378{
1379	struct l2tp_seq *const seq = &priv->seq;
1380	u_int16_t session_id = 0;
1381	int error;
1382
1383	/* If no mbuf passed, send an empty packet (ZLB) */
1384	if (m == NULL) {
1385
1386		/* Create a new mbuf for ZLB packet */
1387		MGETHDR(m, M_DONTWAIT, MT_DATA);
1388		if (m == NULL) {
1389			priv->stats.memoryFailures++;
1390			return (ENOBUFS);
1391		}
1392		m->m_len = m->m_pkthdr.len = 12;
1393		m->m_pkthdr.rcvif = NULL;
1394		priv->stats.xmitZLBs++;
1395	} else {
1396
1397		/* Strip off session ID */
1398		if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) {
1399			priv->stats.memoryFailures++;
1400			return (ENOBUFS);
1401		}
1402		memcpy(&session_id, mtod(m, u_int16_t *), 2);
1403		m_adj(m, 2);
1404
1405		/* Make room for L2TP header */
1406		M_PREPEND(m, 12, M_DONTWAIT);
1407		if (m == NULL) {
1408			priv->stats.memoryFailures++;
1409			return (ENOBUFS);
1410		}
1411	}
1412
1413	/* Fill in L2TP header */
1414	mtod(m, u_int16_t *)[0] = htons(L2TP_CTRL_HDR);
1415	mtod(m, u_int16_t *)[1] = htons(m->m_pkthdr.len);
1416	mtod(m, u_int16_t *)[2] = priv->conf.peer_id;
1417	mtod(m, u_int16_t *)[3] = session_id;
1418	mtod(m, u_int16_t *)[4] = htons(ns);
1419	mtod(m, u_int16_t *)[5] = htons(seq->nr);
1420
1421	/* Update sequence number info and stats */
1422	priv->stats.xmitPackets++;
1423	priv->stats.xmitOctets += m->m_pkthdr.len;
1424
1425	/* Stop ack timer: we're sending an ack with this packet */
1426	if (seq->xack_timer_running && callout_stop(&seq->xack_timer) == 1) {
1427		seq->xack_timer_running = 0;
1428		NG_NODE_UNREF(priv->node);
1429	}
1430	seq->xack = seq->nr;
1431
1432	/* Send packet */
1433	NG_SEND_DATA_ONLY(error, priv->lower, m);
1434	return (error);
1435}
1436
1437#ifdef INVARIANTS
1438/*
1439 * Sanity check sequence number state.
1440 */
1441static void
1442ng_l2tp_seq_check(struct l2tp_seq *seq)
1443{
1444	const int self_unack = L2TP_SEQ_DIFF(seq->nr, seq->xack);
1445	const int peer_unack = L2TP_SEQ_DIFF(seq->ns, seq->rack);
1446	int i;
1447
1448#define CHECK(p)	KASSERT((p), ("%s: not: %s", __FUNCTION__, #p))
1449
1450	CHECK(seq->wmax <= L2TP_MAX_XWIN);
1451	CHECK(seq->cwnd >= 1);
1452	CHECK(seq->cwnd <= seq->wmax);
1453	CHECK(seq->ssth >= 1);
1454	CHECK(seq->ssth <= seq->wmax);
1455	if (seq->cwnd < seq->ssth)
1456		CHECK(seq->acks == 0);
1457	else
1458		CHECK(seq->acks <= seq->cwnd);
1459	CHECK(self_unack >= 0);
1460	CHECK(peer_unack >= 0);
1461	CHECK(peer_unack <= seq->wmax);
1462	CHECK((self_unack == 0) ^ seq->xack_timer_running);
1463	CHECK((peer_unack == 0) ^ seq->rack_timer_running);
1464	CHECK(seq->rack_timer_running || !callout_pending(&seq->rack_timer));
1465	CHECK(seq->xack_timer_running || !callout_pending(&seq->xack_timer));
1466	for (i = 0; i < peer_unack; i++)
1467		CHECK(seq->xwin[i] != NULL);
1468	for ( ; i < seq->cwnd; i++)	    /* verify peer's recv window full */
1469		CHECK(seq->xwin[i] == NULL);
1470
1471#undef CHECK
1472}
1473#endif	/* INVARIANTS */
1474
1475
1476