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