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