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