diff --git a/share/man/man4/ng_l2tp.4 b/share/man/man4/ng_l2tp.4 index 7e4496d61d99..a54cd3a32b8e 100644 --- a/share/man/man4/ng_l2tp.4 +++ b/share/man/man4/ng_l2tp.4 @@ -37,7 +37,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 22, 2002 +.Dd August 2, 2004 .Dt NG_L2TP 4 .Os .Sh NAME @@ -273,6 +273,22 @@ The corresponding session hook must be connected. Same as .Dv NGM_L2TP_GET_STATS , but also atomically clears the statistics as well. +.It Dv NGM_L2TP_SET_SEQ +This command sets the sequence numbers of a not yet enabled node. +It takes a +.Vt "struct ng_l2tp_seq_config" +as argument, where +.Va xack +and +.Va nr +respectively +.Va ns +and +.Va rack +must be the same. +This option is particularly useful if one receives and processes +the first packet entirely in userspace and wants to hand over further +processing to the node. .El .Sh SHUTDOWN This node shuts down upon receipt of a diff --git a/sys/netgraph/ng_l2tp.c b/sys/netgraph/ng_l2tp.c index b3b36c15eb76..4d7efc758e3e 100644 --- a/sys/netgraph/ng_l2tp.c +++ b/sys/netgraph/ng_l2tp.c @@ -171,6 +171,8 @@ static int ng_l2tp_recv_data(node_p node, item_p item, hookpriv_p hpriv); static int ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns); static void ng_l2tp_seq_init(priv_p priv); +static int ng_l2tp_seq_set(priv_p priv, + const struct ng_l2tp_seq_config *conf); static int ng_l2tp_seq_adjust(priv_p priv, const struct ng_l2tp_config *conf); static void ng_l2tp_seq_reset(priv_p priv); @@ -187,6 +189,14 @@ static ng_fn_eachhook ng_l2tp_reset_session; static void ng_l2tp_seq_check(struct l2tp_seq *seq); #endif +/* Parse type for struct ng_l2tp_seq_config. */ +static const struct ng_parse_struct_field + ng_l2tp_seq_config_fields[] = NG_L2TP_SEQ_CONFIG_TYPE_INFO; +static const struct ng_parse_type ng_l2tp_seq_config_type = { + &ng_parse_struct_type, + &ng_l2tp_seq_config_fields +}; + /* Parse type for struct ng_l2tp_config */ static const struct ng_parse_struct_field ng_l2tp_config_type_fields[] = NG_L2TP_CONFIG_TYPE_INFO; @@ -269,6 +279,13 @@ static const struct ng_cmdlist ng_l2tp_cmdlist[] = { NULL, NULL }, + { + NGM_L2TP_COOKIE, + NGM_L2TP_SET_SEQ, + "setsequence", + &ng_l2tp_seq_config_type, + NULL + }, { 0 } }; @@ -457,7 +474,7 @@ ng_l2tp_rcvmsg(node_p node, item_p item, hook_p lasthook) hookpriv_p hpriv; hook_p hook; - /* Check for invalid or illegal config */ + /* Check for invalid or illegal config. */ if (msg->header.arglen != sizeof(*conf)) { error = EINVAL; break; @@ -536,6 +553,25 @@ ng_l2tp_rcvmsg(node_p node, item_p item, hook_p lasthook) memset(&priv->stats, 0, sizeof(priv->stats)); break; } + case NGM_L2TP_SET_SEQ: + { + struct ng_l2tp_seq_config *const conf = + (struct ng_l2tp_seq_config *)msg->data; + + /* Check for invalid or illegal seq config. */ + if (msg->header.arglen != sizeof(*conf)) { + error = EINVAL; + break; + } + conf->ns = htons(conf->ns); + conf->nr = htons(conf->nr); + conf->rack = htons(conf->rack); + conf->xack = htons(conf->xack); + + /* Set sequence numbers. */ + error = ng_l2tp_seq_set(priv, conf); + break; + } default: error = EINVAL; break; @@ -1056,6 +1092,31 @@ ng_l2tp_seq_init(priv_p priv) L2TP_SEQ_CHECK(seq); } +/* + * Set sequence number state as given from user. + */ +static int +ng_l2tp_seq_set(priv_p priv, const struct ng_l2tp_seq_config *conf) +{ + struct l2tp_seq *const seq = &priv->seq; + + /* If node is enabled, deny update to sequence numbers. */ + if (priv->conf.enabled) + return (EBUSY); + + /* We only can handle the simple cases. */ + if (conf->xack != conf->nr || conf->ns != conf->rack) + return (EINVAL); + + /* Set ns,nr,rack,xack parameters. */ + seq->ns = conf->ns; + seq->nr = conf->nr; + seq->rack = conf->rack; + seq->xack = conf->xack; + + return (0); +} + /* * Adjust sequence number state accordingly after reconfiguration. */ diff --git a/sys/netgraph/ng_l2tp.h b/sys/netgraph/ng_l2tp.h index 4fe1d50f82d8..9ceb34355ab0 100644 --- a/sys/netgraph/ng_l2tp.h +++ b/sys/netgraph/ng_l2tp.h @@ -45,7 +45,7 @@ /* Node type name and magic cookie */ #define NG_L2TP_NODE_TYPE "l2tp" -#define NGM_L2TP_COOKIE 1011392401 +#define NGM_L2TP_COOKIE 1091448040 /* Hook names */ #define NG_L2TP_HOOK_CTRL "ctrl" /* control channel hook */ @@ -55,6 +55,21 @@ #define NG_L2TP_HOOK_SESSION_P "session_" /* session data hook (prefix) */ #define NG_L2TP_HOOK_SESSION_F "session_%04x" /* session data hook (format) */ +/* Set intial sequence numbers to not yet enabled node. */ +struct ng_l2tp_seq_config { + u_int16_t ns; /* sequence number to send next */ + u_int16_t nr; /* sequence number to be recved next */ + u_int16_t rack; /* last 'nr' received */ + u_int16_t xack; /* last 'nr' sent */ +}; + +/* Keep this in sync with the above structure definition. */ +#define NG_L2TP_SEQ_CONFIG_TYPE_INFO { \ + { "ns", &ng_parse_uint16_type }, \ + { "nr", &ng_parse_uint16_type }, \ + { NULL } \ +} + /* Configuration for a node */ struct ng_l2tp_config { u_char enabled; /* enables traffic flow */ @@ -156,6 +171,7 @@ enum { NGM_L2TP_CLR_STATS, /* clears stats */ NGM_L2TP_GETCLR_STATS, /* returns & clears stats */ NGM_L2TP_ACK_FAILURE, /* sent *from* node after ack timeout */ + NGM_L2TP_SET_SEQ /* supply a struct ng_l2tp_seq_config */ }; #endif /* _NETGRAPH_NG_L2TP_H_ */