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