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