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 40 /* 41 * L2TP netgraph node type. 42 * 43 * This node type implements the lower layer of the 44 * L2TP protocol as specified in RFC 2661. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/kernel.h> 50 #include <sys/time.h> 51 #include <sys/conf.h> 52 #include <sys/mbuf.h> 53 #include <sys/malloc.h> 54 #include <sys/errno.h> 55 #include <sys/epoch.h> 56 #include <sys/libkern.h> 57 58 #include <net/vnet.h> 59 60 #include <netgraph/ng_message.h> 61 #include <netgraph/netgraph.h> 62 #include <netgraph/ng_parse.h> 63 #include <netgraph/ng_l2tp.h> 64 65 #ifdef NG_SEPARATE_MALLOC 66 static MALLOC_DEFINE(M_NETGRAPH_L2TP, "netgraph_l2tp", "netgraph l2tp node"); 67 #else 68 #define M_NETGRAPH_L2TP M_NETGRAPH 69 #endif 70 71 /* L2TP header format (first 2 bytes only) */ 72 #define L2TP_HDR_CTRL 0x8000 /* control packet */ 73 #define L2TP_HDR_LEN 0x4000 /* has length field */ 74 #define L2TP_HDR_SEQ 0x0800 /* has ns, nr fields */ 75 #define L2TP_HDR_OFF 0x0200 /* has offset field */ 76 #define L2TP_HDR_PRIO 0x0100 /* give priority */ 77 #define L2TP_HDR_VERS_MASK 0x000f /* version field mask */ 78 #define L2TP_HDR_VERSION 0x0002 /* version field */ 79 80 /* Bits that must be zero or one in first two bytes of header */ 81 #define L2TP_CTRL_0BITS 0x030d /* ctrl: must be 0 */ 82 #define L2TP_CTRL_1BITS 0xc802 /* ctrl: must be 1 */ 83 #define L2TP_DATA_0BITS 0x800d /* data: must be 0 */ 84 #define L2TP_DATA_1BITS 0x0002 /* data: must be 1 */ 85 86 /* Standard xmit ctrl and data header bits */ 87 #define L2TP_CTRL_HDR (L2TP_HDR_CTRL | L2TP_HDR_LEN \ 88 | L2TP_HDR_SEQ | L2TP_HDR_VERSION) 89 #define L2TP_DATA_HDR (L2TP_HDR_VERSION) /* optional: len, seq */ 90 91 /* Some hard coded values */ 92 #define L2TP_MAX_XWIN 128 /* my max xmit window */ 93 #define L2TP_MAX_REXMIT 5 /* default max rexmit */ 94 #define L2TP_MAX_REXMIT_TO 30 /* default rexmit to */ 95 #define L2TP_DELAYED_ACK ((hz + 19) / 20) /* delayed ack: 50 ms */ 96 97 /* Default data sequence number configuration for new sessions */ 98 #define L2TP_CONTROL_DSEQ 1 /* we are the lns */ 99 #define L2TP_ENABLE_DSEQ 1 /* enable data seq # */ 100 101 /* Compare sequence numbers using circular math */ 102 #define L2TP_SEQ_DIFF(x, y) ((int16_t)((x) - (y))) 103 104 #define SESSHASHSIZE 0x0020 105 #define SESSHASH(x) (((x) ^ ((x) >> 8)) & (SESSHASHSIZE - 1)) 106 107 /* Hook private data (data session hooks only) */ 108 struct ng_l2tp_hook_private { 109 struct ng_l2tp_sess_config conf; /* hook/session config */ 110 struct ng_l2tp_session_stats stats; /* per sessions statistics */ 111 hook_p hook; /* hook reference */ 112 u_int16_t ns; /* data ns sequence number */ 113 u_int16_t nr; /* data nr sequence number */ 114 LIST_ENTRY(ng_l2tp_hook_private) sessions; 115 }; 116 typedef struct ng_l2tp_hook_private *hookpriv_p; 117 118 /* 119 * Sequence number state 120 * 121 * Invariants: 122 * - If cwnd < ssth, we're doing slow start, otherwise congestion avoidance 123 * - The number of unacknowledged xmit packets is (ns - rack) <= seq->wmax 124 * - The first (ns - rack) mbuf's in xwin[] array are copies of these 125 * unacknowledged packets; the remainder of xwin[] consists first of 126 * zero or more further untransmitted packets in the transmit queue 127 * - We try to keep the peer's receive window as full as possible. 128 * Therefore, (i < cwnd && xwin[i] != NULL) implies (ns - rack) > i. 129 * - rack_timer is running iff (ns - rack) > 0 (unack'd xmit'd pkts) 130 * - If xack != nr, there are unacknowledged recv packet(s) (delayed ack) 131 * - xack_timer is running iff xack != nr (unack'd rec'd pkts) 132 */ 133 struct l2tp_seq { 134 u_int16_t ns; /* next xmit seq we send */ 135 u_int16_t nr; /* next recv seq we expect */ 136 u_int16_t inproc; /* packet is in processing */ 137 u_int16_t rack; /* last 'nr' we rec'd */ 138 u_int16_t xack; /* last 'nr' we sent */ 139 u_int16_t wmax; /* peer's max recv window */ 140 u_int16_t cwnd; /* current congestion window */ 141 u_int16_t ssth; /* slow start threshold */ 142 u_int16_t acks; /* # consecutive acks rec'd */ 143 u_int16_t rexmits; /* # retransmits sent */ 144 struct callout rack_timer; /* retransmit timer */ 145 struct callout xack_timer; /* delayed ack timer */ 146 struct mbuf *xwin[L2TP_MAX_XWIN]; /* transmit window */ 147 struct mtx mtx; /* seq mutex */ 148 }; 149 150 /* Node private data */ 151 struct ng_l2tp_private { 152 node_p node; /* back pointer to node */ 153 hook_p ctrl; /* hook to upper layers */ 154 hook_p lower; /* hook to lower layers */ 155 struct ng_l2tp_config conf; /* node configuration */ 156 struct ng_l2tp_stats stats; /* node statistics */ 157 struct l2tp_seq seq; /* ctrl sequence number state */ 158 ng_ID_t ftarget; /* failure message target */ 159 LIST_HEAD(, ng_l2tp_hook_private) sesshash[SESSHASHSIZE]; 160 }; 161 typedef struct ng_l2tp_private *priv_p; 162 163 /* Netgraph node methods */ 164 static ng_constructor_t ng_l2tp_constructor; 165 static ng_rcvmsg_t ng_l2tp_rcvmsg; 166 static ng_shutdown_t ng_l2tp_shutdown; 167 static ng_newhook_t ng_l2tp_newhook; 168 static ng_rcvdata_t ng_l2tp_rcvdata; 169 static ng_rcvdata_t ng_l2tp_rcvdata_lower; 170 static ng_rcvdata_t ng_l2tp_rcvdata_ctrl; 171 static ng_disconnect_t ng_l2tp_disconnect; 172 173 /* Internal functions */ 174 static int ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns); 175 176 static void ng_l2tp_seq_init(priv_p priv); 177 static int ng_l2tp_seq_set(priv_p priv, 178 const struct ng_l2tp_seq_config *conf); 179 static int ng_l2tp_seq_adjust(priv_p priv, 180 const struct ng_l2tp_config *conf); 181 static void ng_l2tp_seq_reset(priv_p priv); 182 static void ng_l2tp_seq_failure(priv_p priv); 183 static void ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr); 184 static void ng_l2tp_seq_xack_timeout(void *); 185 static void ng_l2tp_seq_rack_timeout(void *); 186 187 static hookpriv_p ng_l2tp_find_session(priv_p privp, u_int16_t sid); 188 static ng_fn_eachhook ng_l2tp_reset_session; 189 190 /* Parse type for struct ng_l2tp_seq_config. */ 191 static const struct ng_parse_struct_field 192 ng_l2tp_seq_config_fields[] = NG_L2TP_SEQ_CONFIG_TYPE_INFO; 193 static const struct ng_parse_type ng_l2tp_seq_config_type = { 194 &ng_parse_struct_type, 195 &ng_l2tp_seq_config_fields 196 }; 197 198 /* Parse type for struct ng_l2tp_config */ 199 static const struct ng_parse_struct_field 200 ng_l2tp_config_type_fields[] = NG_L2TP_CONFIG_TYPE_INFO; 201 static const struct ng_parse_type ng_l2tp_config_type = { 202 &ng_parse_struct_type, 203 &ng_l2tp_config_type_fields, 204 }; 205 206 /* Parse type for struct ng_l2tp_sess_config */ 207 static const struct ng_parse_struct_field 208 ng_l2tp_sess_config_type_fields[] = NG_L2TP_SESS_CONFIG_TYPE_INFO; 209 static const struct ng_parse_type ng_l2tp_sess_config_type = { 210 &ng_parse_struct_type, 211 &ng_l2tp_sess_config_type_fields, 212 }; 213 214 /* Parse type for struct ng_l2tp_stats */ 215 static const struct ng_parse_struct_field 216 ng_l2tp_stats_type_fields[] = NG_L2TP_STATS_TYPE_INFO; 217 static const struct ng_parse_type ng_l2tp_stats_type = { 218 &ng_parse_struct_type, 219 &ng_l2tp_stats_type_fields 220 }; 221 222 /* Parse type for struct ng_l2tp_session_stats. */ 223 static const struct ng_parse_struct_field 224 ng_l2tp_session_stats_type_fields[] = NG_L2TP_SESSION_STATS_TYPE_INFO; 225 static const struct ng_parse_type ng_l2tp_session_stats_type = { 226 &ng_parse_struct_type, 227 &ng_l2tp_session_stats_type_fields 228 }; 229 230 /* List of commands and how to convert arguments to/from ASCII */ 231 static const struct ng_cmdlist ng_l2tp_cmdlist[] = { 232 { 233 NGM_L2TP_COOKIE, 234 NGM_L2TP_SET_CONFIG, 235 "setconfig", 236 &ng_l2tp_config_type, 237 NULL 238 }, 239 { 240 NGM_L2TP_COOKIE, 241 NGM_L2TP_GET_CONFIG, 242 "getconfig", 243 NULL, 244 &ng_l2tp_config_type 245 }, 246 { 247 NGM_L2TP_COOKIE, 248 NGM_L2TP_SET_SESS_CONFIG, 249 "setsessconfig", 250 &ng_l2tp_sess_config_type, 251 NULL 252 }, 253 { 254 NGM_L2TP_COOKIE, 255 NGM_L2TP_GET_SESS_CONFIG, 256 "getsessconfig", 257 &ng_parse_hint16_type, 258 &ng_l2tp_sess_config_type 259 }, 260 { 261 NGM_L2TP_COOKIE, 262 NGM_L2TP_GET_STATS, 263 "getstats", 264 NULL, 265 &ng_l2tp_stats_type 266 }, 267 { 268 NGM_L2TP_COOKIE, 269 NGM_L2TP_CLR_STATS, 270 "clrstats", 271 NULL, 272 NULL 273 }, 274 { 275 NGM_L2TP_COOKIE, 276 NGM_L2TP_GETCLR_STATS, 277 "getclrstats", 278 NULL, 279 &ng_l2tp_stats_type 280 }, 281 { 282 NGM_L2TP_COOKIE, 283 NGM_L2TP_GET_SESSION_STATS, 284 "getsessstats", 285 &ng_parse_int16_type, 286 &ng_l2tp_session_stats_type 287 }, 288 { 289 NGM_L2TP_COOKIE, 290 NGM_L2TP_CLR_SESSION_STATS, 291 "clrsessstats", 292 &ng_parse_int16_type, 293 NULL 294 }, 295 { 296 NGM_L2TP_COOKIE, 297 NGM_L2TP_GETCLR_SESSION_STATS, 298 "getclrsessstats", 299 &ng_parse_int16_type, 300 &ng_l2tp_session_stats_type 301 }, 302 { 303 NGM_L2TP_COOKIE, 304 NGM_L2TP_ACK_FAILURE, 305 "ackfailure", 306 NULL, 307 NULL 308 }, 309 { 310 NGM_L2TP_COOKIE, 311 NGM_L2TP_SET_SEQ, 312 "setsequence", 313 &ng_l2tp_seq_config_type, 314 NULL 315 }, 316 { 0 } 317 }; 318 319 /* Node type descriptor */ 320 static struct ng_type ng_l2tp_typestruct = { 321 .version = NG_ABI_VERSION, 322 .name = NG_L2TP_NODE_TYPE, 323 .constructor = ng_l2tp_constructor, 324 .rcvmsg = ng_l2tp_rcvmsg, 325 .shutdown = ng_l2tp_shutdown, 326 .newhook = ng_l2tp_newhook, 327 .rcvdata = ng_l2tp_rcvdata, 328 .disconnect = ng_l2tp_disconnect, 329 .cmdlist = ng_l2tp_cmdlist, 330 }; 331 NETGRAPH_INIT(l2tp, &ng_l2tp_typestruct); 332 333 /* Sequence number state locking & sanity checking */ 334 #ifdef INVARIANTS 335 static void ng_l2tp_seq_check(struct l2tp_seq *seq); 336 #define SEQ_LOCK(seq) do { \ 337 mtx_lock(&(seq)->mtx); \ 338 ng_l2tp_seq_check(seq); \ 339 } while (0) 340 #define SEQ_UNLOCK(seq) do { \ 341 ng_l2tp_seq_check(seq); \ 342 mtx_unlock(&(seq)->mtx); \ 343 } while (0) 344 #else 345 #define SEQ_LOCK(seq) mtx_lock(&(seq)->mtx) 346 #define SEQ_UNLOCK(seq) mtx_unlock(&(seq)->mtx) 347 #endif 348 #define SEQ_LOCK_ASSERT(seq) mtx_assert(&(seq)->mtx, MA_OWNED) 349 350 /* Whether to use m_copypacket() or m_dup() */ 351 #define L2TP_COPY_MBUF m_copypacket 352 353 #define ERROUT(x) do { error = (x); goto done; } while (0) 354 355 /************************************************************************ 356 NETGRAPH NODE STUFF 357 ************************************************************************/ 358 359 /* 360 * Node type constructor 361 */ 362 static int 363 ng_l2tp_constructor(node_p node) 364 { 365 priv_p priv; 366 int i; 367 368 /* Allocate private structure */ 369 priv = malloc(sizeof(*priv), M_NETGRAPH_L2TP, M_WAITOK | M_ZERO); 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 /* Reset sequence number state */ 659 SEQ_LOCK(seq); 660 ng_l2tp_seq_reset(priv); 661 SEQ_UNLOCK(seq); 662 663 /* Free private data if neither timer is running */ 664 callout_drain(&seq->rack_timer); 665 callout_drain(&seq->xack_timer); 666 667 mtx_destroy(&seq->mtx); 668 669 free(priv, M_NETGRAPH_L2TP); 670 671 /* Unref node */ 672 NG_NODE_UNREF(node); 673 return (0); 674 } 675 676 /* 677 * Hook disconnection 678 */ 679 static int 680 ng_l2tp_disconnect(hook_p hook) 681 { 682 const node_p node = NG_HOOK_NODE(hook); 683 const priv_p priv = NG_NODE_PRIVATE(node); 684 685 /* Zero out hook pointer */ 686 if (hook == priv->ctrl) 687 priv->ctrl = NULL; 688 else if (hook == priv->lower) 689 priv->lower = NULL; 690 else { 691 const hookpriv_p hpriv = NG_HOOK_PRIVATE(hook); 692 LIST_REMOVE(hpriv, sessions); 693 free(hpriv, M_NETGRAPH_L2TP); 694 NG_HOOK_SET_PRIVATE(hook, NULL); 695 } 696 697 /* Go away if no longer connected to anything */ 698 if (NG_NODE_NUMHOOKS(node) == 0 && NG_NODE_IS_VALID(node)) 699 ng_rmnode_self(node); 700 return (0); 701 } 702 703 /************************************************************************* 704 INTERNAL FUNCTIONS 705 *************************************************************************/ 706 707 /* 708 * Find the hook with a given session ID. 709 */ 710 static hookpriv_p 711 ng_l2tp_find_session(priv_p privp, u_int16_t sid) 712 { 713 uint16_t hash = SESSHASH(sid); 714 hookpriv_p hpriv = NULL; 715 716 LIST_FOREACH(hpriv, &privp->sesshash[hash], sessions) { 717 if (hpriv->conf.session_id == sid) 718 break; 719 } 720 721 return (hpriv); 722 } 723 724 /* 725 * Reset a hook's session state. 726 */ 727 static int 728 ng_l2tp_reset_session(hook_p hook, void *arg) 729 { 730 const hookpriv_p hpriv = NG_HOOK_PRIVATE(hook); 731 732 if (hpriv != NULL) { 733 hpriv->conf.control_dseq = 0; 734 hpriv->conf.enable_dseq = 0; 735 bzero(&hpriv->stats, sizeof(struct ng_l2tp_session_stats)); 736 hpriv->nr = 0; 737 hpriv->ns = 0; 738 } 739 return (-1); 740 } 741 742 /* 743 * Handle an incoming frame from below. 744 */ 745 static int 746 ng_l2tp_rcvdata_lower(hook_p h, item_p item) 747 { 748 static const u_int16_t req_bits[2][2] = { 749 { L2TP_DATA_0BITS, L2TP_DATA_1BITS }, 750 { L2TP_CTRL_0BITS, L2TP_CTRL_1BITS }, 751 }; 752 const node_p node = NG_HOOK_NODE(h); 753 const priv_p priv = NG_NODE_PRIVATE(node); 754 hookpriv_p hpriv = NULL; 755 hook_p hook = NULL; 756 struct mbuf *m; 757 u_int16_t tid, sid; 758 u_int16_t hdr; 759 u_int16_t ns, nr; 760 int is_ctrl; 761 int error; 762 int len, plen; 763 764 /* If not configured, reject */ 765 if (!priv->conf.enabled) { 766 NG_FREE_ITEM(item); 767 ERROUT(ENXIO); 768 } 769 770 /* Grab mbuf */ 771 NGI_GET_M(item, m); 772 773 /* Remember full packet length; needed for per session accounting. */ 774 plen = m->m_pkthdr.len; 775 776 /* Update stats */ 777 priv->stats.recvPackets++; 778 priv->stats.recvOctets += plen; 779 780 /* Get initial header */ 781 if (m->m_pkthdr.len < 6) { 782 priv->stats.recvRunts++; 783 NG_FREE_ITEM(item); 784 NG_FREE_M(m); 785 ERROUT(EINVAL); 786 } 787 if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) { 788 priv->stats.memoryFailures++; 789 NG_FREE_ITEM(item); 790 ERROUT(EINVAL); 791 } 792 hdr = (mtod(m, uint8_t *)[0] << 8) + mtod(m, uint8_t *)[1]; 793 m_adj(m, 2); 794 795 /* Check required header bits and minimum length */ 796 is_ctrl = (hdr & L2TP_HDR_CTRL) != 0; 797 if ((hdr & req_bits[is_ctrl][0]) != 0 798 || (~hdr & req_bits[is_ctrl][1]) != 0) { 799 priv->stats.recvInvalid++; 800 NG_FREE_ITEM(item); 801 NG_FREE_M(m); 802 ERROUT(EINVAL); 803 } 804 if (m->m_pkthdr.len < 4 /* tunnel, session id */ 805 + (2 * ((hdr & L2TP_HDR_LEN) != 0)) /* length field */ 806 + (4 * ((hdr & L2TP_HDR_SEQ) != 0)) /* seq # fields */ 807 + (2 * ((hdr & L2TP_HDR_OFF) != 0))) { /* offset field */ 808 priv->stats.recvRunts++; 809 NG_FREE_ITEM(item); 810 NG_FREE_M(m); 811 ERROUT(EINVAL); 812 } 813 814 /* Get and validate length field if present */ 815 if ((hdr & L2TP_HDR_LEN) != 0) { 816 if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) { 817 priv->stats.memoryFailures++; 818 NG_FREE_ITEM(item); 819 ERROUT(EINVAL); 820 } 821 len = (mtod(m, uint8_t *)[0] << 8) + mtod(m, uint8_t *)[1] - 4; 822 m_adj(m, 2); 823 if (len < 0 || len > m->m_pkthdr.len) { 824 priv->stats.recvInvalid++; 825 NG_FREE_ITEM(item); 826 NG_FREE_M(m); 827 ERROUT(EINVAL); 828 } 829 if (len < m->m_pkthdr.len) /* trim extra bytes */ 830 m_adj(m, -(m->m_pkthdr.len - len)); 831 } 832 833 /* Get tunnel ID and session ID */ 834 if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) { 835 priv->stats.memoryFailures++; 836 NG_FREE_ITEM(item); 837 ERROUT(EINVAL); 838 } 839 tid = (mtod(m, u_int8_t *)[0] << 8) + mtod(m, u_int8_t *)[1]; 840 sid = (mtod(m, u_int8_t *)[2] << 8) + mtod(m, u_int8_t *)[3]; 841 m_adj(m, 4); 842 843 /* Check tunnel ID */ 844 if (tid != priv->conf.tunnel_id && 845 (priv->conf.match_id || tid != 0)) { 846 priv->stats.recvWrongTunnel++; 847 NG_FREE_ITEM(item); 848 NG_FREE_M(m); 849 ERROUT(EADDRNOTAVAIL); 850 } 851 852 /* Check session ID (for data packets only) */ 853 if ((hdr & L2TP_HDR_CTRL) == 0) { 854 hpriv = ng_l2tp_find_session(priv, sid); 855 if (hpriv == NULL) { 856 priv->stats.recvUnknownSID++; 857 NG_FREE_ITEM(item); 858 NG_FREE_M(m); 859 ERROUT(ENOTCONN); 860 } 861 hook = hpriv->hook; 862 } 863 864 /* Get Ns, Nr fields if present */ 865 if ((hdr & L2TP_HDR_SEQ) != 0) { 866 if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL) { 867 priv->stats.memoryFailures++; 868 NG_FREE_ITEM(item); 869 ERROUT(EINVAL); 870 } 871 ns = (mtod(m, u_int8_t *)[0] << 8) + mtod(m, u_int8_t *)[1]; 872 nr = (mtod(m, u_int8_t *)[2] << 8) + mtod(m, u_int8_t *)[3]; 873 m_adj(m, 4); 874 } else 875 ns = nr = 0; 876 877 /* Strip offset padding if present */ 878 if ((hdr & L2TP_HDR_OFF) != 0) { 879 u_int16_t offset; 880 881 /* Get length of offset padding */ 882 if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) { 883 priv->stats.memoryFailures++; 884 NG_FREE_ITEM(item); 885 ERROUT(EINVAL); 886 } 887 offset = (mtod(m, u_int8_t *)[0] << 8) + mtod(m, u_int8_t *)[1]; 888 889 /* Trim offset padding */ 890 if ((2+offset) > m->m_pkthdr.len) { 891 priv->stats.recvInvalid++; 892 NG_FREE_ITEM(item); 893 NG_FREE_M(m); 894 ERROUT(EINVAL); 895 } 896 m_adj(m, 2+offset); 897 } 898 899 /* Handle control packets */ 900 if ((hdr & L2TP_HDR_CTRL) != 0) { 901 struct l2tp_seq *const seq = &priv->seq; 902 903 SEQ_LOCK(seq); 904 905 /* Handle receive ack sequence number Nr */ 906 ng_l2tp_seq_recv_nr(priv, nr); 907 908 /* Discard ZLB packets */ 909 if (m->m_pkthdr.len == 0) { 910 SEQ_UNLOCK(seq); 911 priv->stats.recvZLBs++; 912 NG_FREE_ITEM(item); 913 NG_FREE_M(m); 914 ERROUT(0); 915 } 916 917 /* 918 * If not what we expect or we are busy, drop packet and 919 * send an immediate ZLB ack. 920 */ 921 if (ns != seq->nr || seq->inproc) { 922 if (L2TP_SEQ_DIFF(ns, seq->nr) <= 0) 923 priv->stats.recvDuplicates++; 924 else 925 priv->stats.recvOutOfOrder++; 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 /* Prepend session ID to packet. */ 933 M_PREPEND(m, 2, M_NOWAIT); 934 if (m == NULL) { 935 SEQ_UNLOCK(seq); 936 priv->stats.memoryFailures++; 937 NG_FREE_ITEM(item); 938 ERROUT(ENOBUFS); 939 } 940 mtod(m, u_int8_t *)[0] = sid >> 8; 941 mtod(m, u_int8_t *)[1] = sid & 0xff; 942 943 /* 944 * Until we deliver this packet we can't receive next one as 945 * we have no information for sending ack. 946 */ 947 seq->inproc = 1; 948 SEQ_UNLOCK(seq); 949 950 /* Deliver packet to upper layers */ 951 NG_FWD_NEW_DATA(error, item, priv->ctrl, m); 952 953 SEQ_LOCK(seq); 954 /* Ready to process next packet. */ 955 seq->inproc = 0; 956 957 /* If packet was successfully delivered send ack. */ 958 if (error == 0) { 959 /* Update recv sequence number */ 960 seq->nr++; 961 /* Start receive ack timer, if not already running */ 962 if (!callout_active(&seq->xack_timer)) { 963 callout_reset(&seq->xack_timer, 964 L2TP_DELAYED_ACK, ng_l2tp_seq_xack_timeout, 965 node); 966 } 967 } 968 SEQ_UNLOCK(seq); 969 970 ERROUT(error); 971 } 972 973 /* Per session packet, account it. */ 974 hpriv->stats.recvPackets++; 975 hpriv->stats.recvOctets += plen; 976 977 /* Follow peer's lead in data sequencing, if configured to do so */ 978 if (!hpriv->conf.control_dseq) 979 hpriv->conf.enable_dseq = ((hdr & L2TP_HDR_SEQ) != 0); 980 981 /* Handle data sequence numbers if present and enabled */ 982 if ((hdr & L2TP_HDR_SEQ) != 0) { 983 if (hpriv->conf.enable_dseq 984 && L2TP_SEQ_DIFF(ns, hpriv->nr) < 0) { 985 NG_FREE_ITEM(item); /* duplicate or out of order */ 986 NG_FREE_M(m); 987 priv->stats.recvDataDrops++; 988 ERROUT(0); 989 } 990 hpriv->nr = ns + 1; 991 } 992 993 /* Drop empty data packets */ 994 if (m->m_pkthdr.len == 0) { 995 NG_FREE_ITEM(item); 996 NG_FREE_M(m); 997 ERROUT(0); 998 } 999 1000 /* Deliver data */ 1001 NG_FWD_NEW_DATA(error, item, hook, m); 1002 done: 1003 return (error); 1004 } 1005 1006 /* 1007 * Handle an outgoing control frame. 1008 */ 1009 static int 1010 ng_l2tp_rcvdata_ctrl(hook_p hook, item_p item) 1011 { 1012 const node_p node = NG_HOOK_NODE(hook); 1013 const priv_p priv = NG_NODE_PRIVATE(node); 1014 struct l2tp_seq *const seq = &priv->seq; 1015 struct mbuf *m; 1016 int error; 1017 int i; 1018 u_int16_t ns; 1019 1020 /* If not configured, reject */ 1021 if (!priv->conf.enabled) { 1022 NG_FREE_ITEM(item); 1023 ERROUT(ENXIO); 1024 } 1025 1026 /* Grab mbuf and discard other stuff XXX */ 1027 NGI_GET_M(item, m); 1028 NG_FREE_ITEM(item); 1029 1030 /* Packet should have session ID prepended */ 1031 if (m->m_pkthdr.len < 2) { 1032 priv->stats.xmitInvalid++; 1033 m_freem(m); 1034 ERROUT(EINVAL); 1035 } 1036 1037 /* Check max length */ 1038 if (m->m_pkthdr.len >= 0x10000 - 14) { 1039 priv->stats.xmitTooBig++; 1040 m_freem(m); 1041 ERROUT(EOVERFLOW); 1042 } 1043 1044 SEQ_LOCK(seq); 1045 1046 /* Find next empty slot in transmit queue */ 1047 for (i = 0; i < L2TP_MAX_XWIN && seq->xwin[i] != NULL; i++); 1048 if (i == L2TP_MAX_XWIN) { 1049 SEQ_UNLOCK(seq); 1050 priv->stats.xmitDrops++; 1051 m_freem(m); 1052 ERROUT(ENOBUFS); 1053 } 1054 seq->xwin[i] = m; 1055 1056 /* If peer's receive window is already full, nothing else to do */ 1057 if (i >= seq->cwnd) { 1058 SEQ_UNLOCK(seq); 1059 ERROUT(0); 1060 } 1061 1062 /* Start retransmit timer if not already running */ 1063 if (!callout_active(&seq->rack_timer)) 1064 callout_reset(&seq->rack_timer, hz, ng_l2tp_seq_rack_timeout, 1065 node); 1066 1067 ns = seq->ns++; 1068 1069 /* Copy packet */ 1070 if ((m = L2TP_COPY_MBUF(m, M_NOWAIT)) == NULL) { 1071 SEQ_UNLOCK(seq); 1072 priv->stats.memoryFailures++; 1073 ERROUT(ENOBUFS); 1074 } 1075 1076 /* Send packet and increment xmit sequence number */ 1077 error = ng_l2tp_xmit_ctrl(priv, m, ns); 1078 done: 1079 return (error); 1080 } 1081 1082 /* 1083 * Handle an outgoing data frame. 1084 */ 1085 static int 1086 ng_l2tp_rcvdata(hook_p hook, item_p item) 1087 { 1088 const priv_p priv = NG_NODE_PRIVATE(NG_HOOK_NODE(hook)); 1089 const hookpriv_p hpriv = NG_HOOK_PRIVATE(hook); 1090 struct mbuf *m; 1091 uint8_t *p; 1092 u_int16_t hdr; 1093 int error; 1094 int i = 2; 1095 1096 /* If not configured, reject */ 1097 if (!priv->conf.enabled) { 1098 NG_FREE_ITEM(item); 1099 ERROUT(ENXIO); 1100 } 1101 1102 /* Get mbuf */ 1103 NGI_GET_M(item, m); 1104 1105 /* Check max length */ 1106 if (m->m_pkthdr.len >= 0x10000 - 12) { 1107 priv->stats.xmitDataTooBig++; 1108 NG_FREE_ITEM(item); 1109 NG_FREE_M(m); 1110 ERROUT(EOVERFLOW); 1111 } 1112 1113 /* Prepend L2TP header */ 1114 M_PREPEND(m, 6 1115 + (2 * (hpriv->conf.include_length != 0)) 1116 + (4 * (hpriv->conf.enable_dseq != 0)), 1117 M_NOWAIT); 1118 if (m == NULL) { 1119 priv->stats.memoryFailures++; 1120 NG_FREE_ITEM(item); 1121 ERROUT(ENOBUFS); 1122 } 1123 p = mtod(m, uint8_t *); 1124 hdr = L2TP_DATA_HDR; 1125 if (hpriv->conf.include_length) { 1126 hdr |= L2TP_HDR_LEN; 1127 p[i++] = m->m_pkthdr.len >> 8; 1128 p[i++] = m->m_pkthdr.len & 0xff; 1129 } 1130 p[i++] = priv->conf.peer_id >> 8; 1131 p[i++] = priv->conf.peer_id & 0xff; 1132 p[i++] = hpriv->conf.peer_id >> 8; 1133 p[i++] = hpriv->conf.peer_id & 0xff; 1134 if (hpriv->conf.enable_dseq) { 1135 hdr |= L2TP_HDR_SEQ; 1136 p[i++] = hpriv->ns >> 8; 1137 p[i++] = hpriv->ns & 0xff; 1138 p[i++] = hpriv->nr >> 8; 1139 p[i++] = hpriv->nr & 0xff; 1140 hpriv->ns++; 1141 } 1142 p[0] = hdr >> 8; 1143 p[1] = hdr & 0xff; 1144 1145 /* Update per session stats. */ 1146 hpriv->stats.xmitPackets++; 1147 hpriv->stats.xmitOctets += m->m_pkthdr.len; 1148 1149 /* And the global one. */ 1150 priv->stats.xmitPackets++; 1151 priv->stats.xmitOctets += m->m_pkthdr.len; 1152 1153 /* Send packet */ 1154 NG_FWD_NEW_DATA(error, item, priv->lower, m); 1155 done: 1156 return (error); 1157 } 1158 1159 /* 1160 * Send a message to our controlling node that we've failed. 1161 */ 1162 static void 1163 ng_l2tp_seq_failure(priv_p priv) 1164 { 1165 struct ng_mesg *msg; 1166 int error; 1167 1168 NG_MKMESSAGE(msg, NGM_L2TP_COOKIE, NGM_L2TP_ACK_FAILURE, 0, M_NOWAIT); 1169 if (msg == NULL) 1170 return; 1171 NG_SEND_MSG_ID(error, priv->node, msg, priv->ftarget, 0); 1172 } 1173 1174 /************************************************************************ 1175 SEQUENCE NUMBER HANDLING 1176 ************************************************************************/ 1177 1178 /* 1179 * Initialize sequence number state. 1180 */ 1181 static void 1182 ng_l2tp_seq_init(priv_p priv) 1183 { 1184 struct l2tp_seq *const seq = &priv->seq; 1185 1186 KASSERT(priv->conf.peer_win >= 1, 1187 ("%s: peer_win is zero", __func__)); 1188 memset(seq, 0, sizeof(*seq)); 1189 seq->cwnd = 1; 1190 seq->wmax = priv->conf.peer_win; 1191 if (seq->wmax > L2TP_MAX_XWIN) 1192 seq->wmax = L2TP_MAX_XWIN; 1193 seq->ssth = seq->wmax; 1194 mtx_init(&seq->mtx, "ng_l2tp", NULL, MTX_DEF); 1195 callout_init_mtx(&seq->rack_timer, &seq->mtx, CALLOUT_RETURNUNLOCKED); 1196 callout_init_mtx(&seq->xack_timer, &seq->mtx, CALLOUT_RETURNUNLOCKED); 1197 } 1198 1199 /* 1200 * Set sequence number state as given from user. 1201 */ 1202 static int 1203 ng_l2tp_seq_set(priv_p priv, const struct ng_l2tp_seq_config *conf) 1204 { 1205 struct l2tp_seq *const seq = &priv->seq; 1206 1207 /* If node is enabled, deny update to sequence numbers. */ 1208 if (priv->conf.enabled) 1209 return (EBUSY); 1210 1211 /* We only can handle the simple cases. */ 1212 if (conf->xack != conf->nr || conf->ns != conf->rack) 1213 return (EINVAL); 1214 1215 /* Set ns,nr,rack,xack parameters. */ 1216 seq->ns = conf->ns; 1217 seq->nr = conf->nr; 1218 seq->rack = conf->rack; 1219 seq->xack = conf->xack; 1220 1221 return (0); 1222 } 1223 1224 /* 1225 * Adjust sequence number state accordingly after reconfiguration. 1226 */ 1227 static int 1228 ng_l2tp_seq_adjust(priv_p priv, const struct ng_l2tp_config *conf) 1229 { 1230 struct l2tp_seq *const seq = &priv->seq; 1231 u_int16_t new_wmax; 1232 int error = 0; 1233 1234 SEQ_LOCK(seq); 1235 /* If disabling node, reset state sequence number */ 1236 if (!conf->enabled) { 1237 ng_l2tp_seq_reset(priv); 1238 SEQ_UNLOCK(seq); 1239 return (0); 1240 } 1241 1242 /* Adjust peer's max recv window; it can only increase */ 1243 new_wmax = conf->peer_win; 1244 if (new_wmax > L2TP_MAX_XWIN) 1245 new_wmax = L2TP_MAX_XWIN; 1246 if (new_wmax == 0) 1247 ERROUT(EINVAL); 1248 if (new_wmax < seq->wmax) 1249 ERROUT(EBUSY); 1250 seq->wmax = new_wmax; 1251 1252 done: 1253 SEQ_UNLOCK(seq); 1254 return (error); 1255 } 1256 1257 /* 1258 * Reset sequence number state. 1259 */ 1260 static void 1261 ng_l2tp_seq_reset(priv_p priv) 1262 { 1263 struct l2tp_seq *const seq = &priv->seq; 1264 int i; 1265 1266 SEQ_LOCK_ASSERT(seq); 1267 1268 /* Stop timers */ 1269 (void )callout_stop(&seq->rack_timer); 1270 (void )callout_stop(&seq->xack_timer); 1271 1272 /* Free retransmit queue */ 1273 for (i = 0; i < L2TP_MAX_XWIN; i++) { 1274 if (seq->xwin[i] == NULL) 1275 break; 1276 m_freem(seq->xwin[i]); 1277 } 1278 1279 /* Reset session hooks' sequence number states */ 1280 NG_NODE_FOREACH_HOOK(priv->node, ng_l2tp_reset_session, NULL); 1281 1282 /* Reset node's sequence number state */ 1283 seq->ns = 0; 1284 seq->nr = 0; 1285 seq->rack = 0; 1286 seq->xack = 0; 1287 seq->wmax = L2TP_MAX_XWIN; 1288 seq->cwnd = 1; 1289 seq->ssth = seq->wmax; 1290 seq->acks = 0; 1291 seq->rexmits = 0; 1292 bzero(seq->xwin, sizeof(seq->xwin)); 1293 } 1294 1295 /* 1296 * Handle receipt of an acknowledgement value (Nr) from peer. 1297 */ 1298 static void 1299 ng_l2tp_seq_recv_nr(priv_p priv, u_int16_t nr) 1300 { 1301 struct l2tp_seq *const seq = &priv->seq; 1302 struct mbuf *xwin[L2TP_MAX_XWIN]; /* partial local copy */ 1303 int nack; 1304 int i, j; 1305 uint16_t ns; 1306 1307 SEQ_LOCK_ASSERT(seq); 1308 1309 /* Verify peer's ACK is in range */ 1310 if ((nack = L2TP_SEQ_DIFF(nr, seq->rack)) <= 0) 1311 return; /* duplicate ack */ 1312 if (L2TP_SEQ_DIFF(nr, seq->ns) > 0) { 1313 priv->stats.recvBadAcks++; /* ack for packet not sent */ 1314 return; 1315 } 1316 KASSERT(nack <= L2TP_MAX_XWIN, 1317 ("%s: nack=%d > %d", __func__, nack, L2TP_MAX_XWIN)); 1318 1319 /* Update receive ack stats */ 1320 seq->rack = nr; 1321 seq->rexmits = 0; 1322 1323 /* Free acknowledged packets and shift up packets in the xmit queue */ 1324 for (i = 0; i < nack; i++) 1325 m_freem(seq->xwin[i]); 1326 memmove(seq->xwin, seq->xwin + nack, 1327 (L2TP_MAX_XWIN - nack) * sizeof(*seq->xwin)); 1328 memset(seq->xwin + (L2TP_MAX_XWIN - nack), 0, 1329 nack * sizeof(*seq->xwin)); 1330 1331 /* 1332 * Do slow-start/congestion avoidance windowing algorithm described 1333 * in RFC 2661, Appendix A. Here we handle a multiple ACK as if each 1334 * ACK had arrived separately. 1335 */ 1336 if (seq->cwnd < seq->wmax) { 1337 /* Handle slow start phase */ 1338 if (seq->cwnd < seq->ssth) { 1339 seq->cwnd += nack; 1340 nack = 0; 1341 if (seq->cwnd > seq->ssth) { /* into cg.av. phase */ 1342 nack = seq->cwnd - seq->ssth; 1343 seq->cwnd = seq->ssth; 1344 } 1345 } 1346 1347 /* Handle congestion avoidance phase */ 1348 if (seq->cwnd >= seq->ssth) { 1349 seq->acks += nack; 1350 while (seq->acks >= seq->cwnd) { 1351 seq->acks -= seq->cwnd; 1352 if (seq->cwnd < seq->wmax) 1353 seq->cwnd++; 1354 } 1355 } 1356 } 1357 1358 /* Stop xmit timer */ 1359 if (callout_active(&seq->rack_timer)) 1360 (void )callout_stop(&seq->rack_timer); 1361 1362 /* If transmit queue is empty, we're done for now */ 1363 if (seq->xwin[0] == NULL) 1364 return; 1365 1366 /* Start restransmit timer again */ 1367 callout_reset(&seq->rack_timer, hz, ng_l2tp_seq_rack_timeout, 1368 priv->node); 1369 1370 /* 1371 * Send more packets, trying to keep peer's receive window full. 1372 * Make copy of everything we need before lock release. 1373 */ 1374 ns = seq->ns; 1375 j = 0; 1376 while ((i = L2TP_SEQ_DIFF(seq->ns, seq->rack)) < seq->cwnd 1377 && seq->xwin[i] != NULL) { 1378 xwin[j++] = seq->xwin[i]; 1379 seq->ns++; 1380 } 1381 1382 /* 1383 * Send prepared. 1384 * If there is a memory error, pretend packet was sent, as it 1385 * will get retransmitted later anyway. 1386 */ 1387 for (i = 0; i < j; i++) { 1388 struct mbuf *m; 1389 if ((m = L2TP_COPY_MBUF(xwin[i], M_NOWAIT)) == NULL) 1390 priv->stats.memoryFailures++; 1391 else { 1392 ng_l2tp_xmit_ctrl(priv, m, ns); 1393 SEQ_LOCK(seq); 1394 } 1395 ns++; 1396 } 1397 } 1398 1399 /* 1400 * Handle an ack timeout. We have an outstanding ack that we 1401 * were hoping to piggy-back, but haven't, so send a ZLB. 1402 */ 1403 static void 1404 ng_l2tp_seq_xack_timeout(void *arg) 1405 { 1406 const node_p node = arg; 1407 const priv_p priv = NG_NODE_PRIVATE(node); 1408 struct epoch_tracker et; 1409 struct l2tp_seq *const seq = &priv->seq; 1410 1411 SEQ_LOCK_ASSERT(seq); 1412 MPASS(!callout_pending(&seq->xack_timer)); 1413 MPASS(callout_active(&seq->xack_timer)); 1414 1415 NET_EPOCH_ENTER(et); 1416 CURVNET_SET(node->nd_vnet); 1417 /* Send a ZLB */ 1418 ng_l2tp_xmit_ctrl(priv, NULL, seq->ns); 1419 CURVNET_RESTORE(); 1420 NET_EPOCH_EXIT(et); 1421 1422 /* callout_deactivate() is not needed here 1423 as callout_stop() was called by ng_l2tp_xmit_ctrl() */ 1424 } 1425 1426 /* 1427 * Handle a transmit timeout. The peer has failed to respond 1428 * with an ack for our packet, so retransmit it. 1429 */ 1430 static void 1431 ng_l2tp_seq_rack_timeout(void *arg) 1432 { 1433 const node_p node = arg; 1434 const priv_p priv = NG_NODE_PRIVATE(node); 1435 struct epoch_tracker et; 1436 struct l2tp_seq *const seq = &priv->seq; 1437 struct mbuf *m; 1438 u_int delay; 1439 1440 SEQ_LOCK_ASSERT(seq); 1441 MPASS(seq->xwin[0]); 1442 MPASS(!callout_pending(&seq->rack_timer)); 1443 MPASS(callout_active(&seq->rack_timer)); 1444 1445 NET_EPOCH_ENTER(et); 1446 CURVNET_SET(node->nd_vnet); 1447 1448 priv->stats.xmitRetransmits++; 1449 1450 /* Have we reached the retransmit limit? If so, notify owner. */ 1451 if (seq->rexmits++ >= priv->conf.rexmit_max) 1452 ng_l2tp_seq_failure(priv); 1453 1454 /* Restart timer, this time with an increased delay */ 1455 delay = (seq->rexmits > 12) ? (1 << 12) : (1 << seq->rexmits); 1456 if (delay > priv->conf.rexmit_max_to) 1457 delay = priv->conf.rexmit_max_to; 1458 callout_reset(&seq->rack_timer, hz * delay, ng_l2tp_seq_rack_timeout, 1459 node); 1460 1461 /* Do slow-start/congestion algorithm windowing algorithm */ 1462 seq->ns = seq->rack; 1463 seq->ssth = (seq->cwnd + 1) / 2; 1464 seq->cwnd = 1; 1465 seq->acks = 0; 1466 1467 /* Retransmit oldest unack'd packet */ 1468 m = L2TP_COPY_MBUF(seq->xwin[0], M_NOWAIT); 1469 if (m == NULL) { 1470 SEQ_UNLOCK(seq); 1471 priv->stats.memoryFailures++; 1472 } else 1473 ng_l2tp_xmit_ctrl(priv, m, seq->ns++); 1474 1475 CURVNET_RESTORE(); 1476 NET_EPOCH_EXIT(et); 1477 1478 /* callout_deactivate() is not needed here 1479 as ng_callout() is getting called each time */ 1480 } 1481 1482 /* 1483 * Transmit a control stream packet, payload optional. 1484 * The transmit sequence number is not incremented. 1485 * Requires seq lock, returns unlocked. 1486 */ 1487 static int 1488 ng_l2tp_xmit_ctrl(priv_p priv, struct mbuf *m, u_int16_t ns) 1489 { 1490 struct l2tp_seq *const seq = &priv->seq; 1491 uint8_t *p; 1492 uint16_t nr, session_id = 0; 1493 int error; 1494 1495 SEQ_LOCK_ASSERT(seq); 1496 1497 /* Stop ack timer: we're sending an ack with this packet. 1498 Doing this before to keep state predictable after error. */ 1499 if (callout_active(&seq->xack_timer)) 1500 (void )callout_stop(&seq->xack_timer); 1501 1502 nr = seq->xack = seq->nr; 1503 1504 SEQ_UNLOCK(seq); 1505 1506 /* If no mbuf passed, send an empty packet (ZLB) */ 1507 if (m == NULL) { 1508 /* Create a new mbuf for ZLB packet */ 1509 MGETHDR(m, M_NOWAIT, MT_DATA); 1510 if (m == NULL) { 1511 priv->stats.memoryFailures++; 1512 return (ENOBUFS); 1513 } 1514 m->m_len = m->m_pkthdr.len = 12; 1515 m->m_pkthdr.rcvif = NULL; 1516 priv->stats.xmitZLBs++; 1517 } else { 1518 /* Strip off session ID */ 1519 if (m->m_len < 2 && (m = m_pullup(m, 2)) == NULL) { 1520 priv->stats.memoryFailures++; 1521 return (ENOBUFS); 1522 } 1523 session_id = (mtod(m, u_int8_t *)[0] << 8) + mtod(m, u_int8_t *)[1]; 1524 1525 /* Make room for L2TP header */ 1526 M_PREPEND(m, 10, M_NOWAIT); /* - 2 + 12 = 10 */ 1527 if (m == NULL) { 1528 priv->stats.memoryFailures++; 1529 return (ENOBUFS); 1530 } 1531 1532 /* 1533 * The below requires 12 contiguous bytes for the L2TP header 1534 * to be written into. 1535 */ 1536 m = m_pullup(m, 12); 1537 if (m == NULL) { 1538 priv->stats.memoryFailures++; 1539 return (ENOBUFS); 1540 } 1541 } 1542 1543 /* Fill in L2TP header */ 1544 p = mtod(m, u_int8_t *); 1545 p[0] = L2TP_CTRL_HDR >> 8; 1546 p[1] = L2TP_CTRL_HDR & 0xff; 1547 p[2] = m->m_pkthdr.len >> 8; 1548 p[3] = m->m_pkthdr.len & 0xff; 1549 p[4] = priv->conf.peer_id >> 8; 1550 p[5] = priv->conf.peer_id & 0xff; 1551 p[6] = session_id >> 8; 1552 p[7] = session_id & 0xff; 1553 p[8] = ns >> 8; 1554 p[9] = ns & 0xff; 1555 p[10] = nr >> 8; 1556 p[11] = nr & 0xff; 1557 1558 /* Update sequence number info and stats */ 1559 priv->stats.xmitPackets++; 1560 priv->stats.xmitOctets += m->m_pkthdr.len; 1561 1562 /* Send packet */ 1563 NG_SEND_DATA_ONLY(error, priv->lower, m); 1564 return (error); 1565 } 1566 1567 #ifdef INVARIANTS 1568 /* 1569 * Sanity check sequence number state. 1570 */ 1571 static void 1572 ng_l2tp_seq_check(struct l2tp_seq *seq) 1573 { 1574 int self_unack, peer_unack; 1575 int i; 1576 1577 #define CHECK(p) KASSERT((p), ("%s: not: %s", __func__, #p)) 1578 1579 SEQ_LOCK_ASSERT(seq); 1580 1581 self_unack = L2TP_SEQ_DIFF(seq->nr, seq->xack); 1582 peer_unack = L2TP_SEQ_DIFF(seq->ns, seq->rack); 1583 CHECK(seq->wmax <= L2TP_MAX_XWIN); 1584 CHECK(seq->cwnd >= 1); 1585 CHECK(seq->cwnd <= seq->wmax); 1586 CHECK(seq->ssth >= 1); 1587 CHECK(seq->ssth <= seq->wmax); 1588 if (seq->cwnd < seq->ssth) 1589 CHECK(seq->acks == 0); 1590 else 1591 CHECK(seq->acks <= seq->cwnd); 1592 CHECK(self_unack >= 0); 1593 CHECK(peer_unack >= 0); 1594 CHECK(peer_unack <= seq->wmax); 1595 CHECK((self_unack == 0) ^ callout_active(&seq->xack_timer)); 1596 CHECK((peer_unack == 0) ^ callout_active(&seq->rack_timer)); 1597 for (i = 0; i < peer_unack; i++) 1598 CHECK(seq->xwin[i] != NULL); 1599 for ( ; i < seq->cwnd; i++) /* verify peer's recv window full */ 1600 CHECK(seq->xwin[i] == NULL); 1601 1602 #undef CHECK 1603 } 1604 #endif /* INVARIANTS */ 1605