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