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