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