1 2 /* 3 * ng_pptpgre.c 4 * 5 * Copyright (c) 1996-1999 Whistle Communications, Inc. 6 * All rights reserved. 7 * 8 * Subject to the following obligations and disclaimer of warranty, use and 9 * redistribution of this software, in source or object code forms, with or 10 * without modifications are expressly permitted by Whistle Communications; 11 * provided, however, that: 12 * 1. Any and all reproductions of the source or object code must include the 13 * copyright notice above and the following disclaimer of warranties; and 14 * 2. No rights are granted, in any manner or form, to use Whistle 15 * Communications, Inc. trademarks, including the mark "WHISTLE 16 * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 17 * such appears in the above copyright notice or in the software. 18 * 19 * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 20 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 21 * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 22 * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 24 * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 25 * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 26 * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 27 * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 28 * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 29 * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 30 * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 31 * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 35 * OF SUCH DAMAGE. 36 * 37 * Author: Archie Cobbs <archie@freebsd.org> 38 * 39 * $FreeBSD$ 40 * $Whistle: ng_pptpgre.c,v 1.7 1999/12/08 00:10:06 archie Exp $ 41 */ 42 43 /* 44 * PPTP/GRE netgraph node type. 45 * 46 * This node type does the GRE encapsulation as specified for the PPTP 47 * protocol (RFC 2637, section 4). This includes sequencing and 48 * retransmission of frames, but not the actual packet delivery nor 49 * any of the TCP control stream protocol. 50 * 51 * The "upper" hook of this node is suitable for attaching to a "ppp" 52 * node link hook. The "lower" hook of this node is suitable for attaching 53 * to a "ksocket" node on hook "inet/raw/gre". 54 */ 55 56 #include <sys/param.h> 57 #include <sys/systm.h> 58 #include <sys/kernel.h> 59 #include <sys/time.h> 60 #include <sys/mbuf.h> 61 #include <sys/malloc.h> 62 #include <sys/errno.h> 63 64 #include <netinet/in.h> 65 #include <netinet/in_systm.h> 66 #include <netinet/ip.h> 67 68 #include <netgraph/ng_message.h> 69 #include <netgraph/netgraph.h> 70 #include <netgraph/ng_parse.h> 71 #include <netgraph/ng_pptpgre.h> 72 73 /* GRE packet format, as used by PPTP */ 74 struct greheader { 75 #if BYTE_ORDER == LITTLE_ENDIAN 76 u_char recursion:3; /* recursion control */ 77 u_char ssr:1; /* strict source route */ 78 u_char hasSeq:1; /* sequence number present */ 79 u_char hasKey:1; /* key present */ 80 u_char hasRoute:1; /* routing present */ 81 u_char hasSum:1; /* checksum present */ 82 u_char vers:3; /* version */ 83 u_char flags:4; /* flags */ 84 u_char hasAck:1; /* acknowlege number present */ 85 #elif BYTE_ORDER == BIG_ENDIAN 86 u_char hasSum:1; /* checksum present */ 87 u_char hasRoute:1; /* routing present */ 88 u_char hasKey:1; /* key present */ 89 u_char hasSeq:1; /* sequence number present */ 90 u_char ssr:1; /* strict source route */ 91 u_char recursion:3; /* recursion control */ 92 u_char hasAck:1; /* acknowlege number present */ 93 u_char flags:4; /* flags */ 94 u_char vers:3; /* version */ 95 #else 96 #error BYTE_ORDER is not defined properly 97 #endif 98 u_int16_t proto; /* protocol (ethertype) */ 99 u_int16_t length; /* payload length */ 100 u_int16_t cid; /* call id */ 101 u_int32_t data[0]; /* opt. seq, ack, then data */ 102 }; 103 104 /* The PPTP protocol ID used in the GRE 'proto' field */ 105 #define PPTP_GRE_PROTO 0x880b 106 107 /* Bits that must be set a certain way in all PPTP/GRE packets */ 108 #define PPTP_INIT_VALUE ((0x2001 << 16) | PPTP_GRE_PROTO) 109 #define PPTP_INIT_MASK 0xef7fffff 110 111 /* Min and max packet length */ 112 #define PPTP_MAX_PAYLOAD (0xffff - sizeof(struct greheader) - 8) 113 114 /* All times are scaled by this (PPTP_TIME_SCALE time units = 1 sec.) */ 115 #define PPTP_TIME_SCALE 1000 /* milliseconds */ 116 typedef u_int64_t pptptime_t; 117 118 /* Acknowledgment timeout parameters and functions */ 119 #define PPTP_XMIT_WIN 16 /* max xmit window */ 120 #define PPTP_MIN_RTT (PPTP_TIME_SCALE / 10) /* 100 milliseconds */ 121 #define PPTP_MIN_TIMEOUT (PPTP_TIME_SCALE / 500) /* 2 milliseconds */ 122 #define PPTP_MAX_TIMEOUT (10 * PPTP_TIME_SCALE) /* 10 seconds */ 123 124 /* When we recieve a packet, we wait to see if there's an outgoing packet 125 we can piggy-back the ACK off of. These parameters determine the mimimum 126 and maxmimum length of time we're willing to wait in order to do that. 127 These have no effect unless "enableDelayedAck" is turned on. */ 128 #define PPTP_MIN_ACK_DELAY (PPTP_TIME_SCALE / 500) /* 2 milliseconds */ 129 #define PPTP_MAX_ACK_DELAY (PPTP_TIME_SCALE / 2) /* 500 milliseconds */ 130 131 /* See RFC 2637 section 4.4 */ 132 #define PPTP_ACK_ALPHA(x) ((x) >> 3) /* alpha = 0.125 */ 133 #define PPTP_ACK_BETA(x) ((x) >> 2) /* beta = 0.25 */ 134 #define PPTP_ACK_CHI(x) ((x) << 2) /* chi = 4 */ 135 #define PPTP_ACK_DELTA(x) ((x) << 1) /* delta = 2 */ 136 137 #define PPTP_SEQ_DIFF(x,y) ((int32_t)(x) - (int32_t)(y)) 138 139 /* We keep packet retransmit and acknowlegement state in this struct */ 140 struct ng_pptpgre_ackp { 141 int32_t ato; /* adaptive time-out value */ 142 int32_t rtt; /* round trip time estimate */ 143 int32_t dev; /* deviation estimate */ 144 u_int16_t xmitWin; /* size of xmit window */ 145 struct callout_handle sackTimer; /* send ack timer */ 146 struct callout_handle rackTimer; /* recv ack timer */ 147 node_p *sackTimerPtr; /* send ack timer pointer */ 148 node_p *rackTimerPtr; /* recv ack timer pointer */ 149 u_int32_t winAck; /* seq when xmitWin will grow */ 150 pptptime_t timeSent[PPTP_XMIT_WIN]; 151 #ifdef DEBUG_RAT 152 pptptime_t timerStart; /* when rackTimer started */ 153 pptptime_t timerLength; /* rackTimer duration */ 154 #endif 155 }; 156 157 /* Node private data */ 158 struct ng_pptpgre_private { 159 hook_p upper; /* hook to upper layers */ 160 hook_p lower; /* hook to lower layers */ 161 struct ng_pptpgre_conf conf; /* configuration info */ 162 struct ng_pptpgre_ackp ackp; /* packet transmit ack state */ 163 u_int32_t recvSeq; /* last seq # we rcv'd */ 164 u_int32_t xmitSeq; /* last seq # we sent */ 165 u_int32_t recvAck; /* last seq # peer ack'd */ 166 u_int32_t xmitAck; /* last seq # we ack'd */ 167 struct timeval startTime; /* time node was created */ 168 struct ng_pptpgre_stats stats; /* node statistics */ 169 }; 170 typedef struct ng_pptpgre_private *priv_p; 171 172 /* Netgraph node methods */ 173 static ng_constructor_t ng_pptpgre_constructor; 174 static ng_rcvmsg_t ng_pptpgre_rcvmsg; 175 static ng_shutdown_t ng_pptpgre_shutdown; 176 static ng_newhook_t ng_pptpgre_newhook; 177 static ng_rcvdata_t ng_pptpgre_rcvdata; 178 static ng_disconnect_t ng_pptpgre_disconnect; 179 180 /* Helper functions */ 181 static int ng_pptpgre_xmit(node_p node, item_p item); 182 static int ng_pptpgre_recv(node_p node, item_p item); 183 static void ng_pptpgre_start_send_ack_timer(node_p node, int ackTimeout); 184 static void ng_pptpgre_start_recv_ack_timer(node_p node); 185 static void ng_pptpgre_recv_ack_timeout(void *arg); 186 static void ng_pptpgre_send_ack_timeout(void *arg); 187 static void ng_pptpgre_reset(node_p node); 188 static pptptime_t ng_pptpgre_time(node_p node); 189 190 /* Parse type for struct ng_pptpgre_conf */ 191 static const struct ng_parse_struct_info 192 ng_pptpgre_conf_type_info = NG_PPTPGRE_CONF_TYPE_INFO; 193 static const struct ng_parse_type ng_pptpgre_conf_type = { 194 &ng_parse_struct_type, 195 &ng_pptpgre_conf_type_info, 196 }; 197 198 /* Parse type for struct ng_pptpgre_stats */ 199 static const struct ng_parse_struct_info 200 ng_pptpgre_stats_type_info = NG_PPTPGRE_STATS_TYPE_INFO; 201 static const struct ng_parse_type ng_pptp_stats_type = { 202 &ng_parse_struct_type, 203 &ng_pptpgre_stats_type_info 204 }; 205 206 /* List of commands and how to convert arguments to/from ASCII */ 207 static const struct ng_cmdlist ng_pptpgre_cmdlist[] = { 208 { 209 NGM_PPTPGRE_COOKIE, 210 NGM_PPTPGRE_SET_CONFIG, 211 "setconfig", 212 &ng_pptpgre_conf_type, 213 NULL 214 }, 215 { 216 NGM_PPTPGRE_COOKIE, 217 NGM_PPTPGRE_GET_CONFIG, 218 "getconfig", 219 NULL, 220 &ng_pptpgre_conf_type 221 }, 222 { 223 NGM_PPTPGRE_COOKIE, 224 NGM_PPTPGRE_GET_STATS, 225 "getstats", 226 NULL, 227 &ng_pptp_stats_type 228 }, 229 { 230 NGM_PPTPGRE_COOKIE, 231 NGM_PPTPGRE_CLR_STATS, 232 "clrstats", 233 NULL, 234 NULL 235 }, 236 { 237 NGM_PPTPGRE_COOKIE, 238 NGM_PPTPGRE_GETCLR_STATS, 239 "getclrstats", 240 NULL, 241 &ng_pptp_stats_type 242 }, 243 { 0 } 244 }; 245 246 /* Node type descriptor */ 247 static struct ng_type ng_pptpgre_typestruct = { 248 NG_ABI_VERSION, 249 NG_PPTPGRE_NODE_TYPE, 250 NULL, 251 ng_pptpgre_constructor, 252 ng_pptpgre_rcvmsg, 253 ng_pptpgre_shutdown, 254 ng_pptpgre_newhook, 255 NULL, 256 NULL, 257 ng_pptpgre_rcvdata, 258 ng_pptpgre_disconnect, 259 ng_pptpgre_cmdlist 260 }; 261 NETGRAPH_INIT(pptpgre, &ng_pptpgre_typestruct); 262 263 #define ERROUT(x) do { error = (x); goto done; } while (0) 264 265 /************************************************************************ 266 NETGRAPH NODE STUFF 267 ************************************************************************/ 268 269 /* 270 * Node type constructor 271 */ 272 static int 273 ng_pptpgre_constructor(node_p node) 274 { 275 priv_p priv; 276 277 /* Allocate private structure */ 278 MALLOC(priv, priv_p, sizeof(*priv), M_NETGRAPH, M_NOWAIT | M_ZERO); 279 if (priv == NULL) 280 return (ENOMEM); 281 282 NG_NODE_SET_PRIVATE(node, priv); 283 284 /* Initialize state */ 285 callout_handle_init(&priv->ackp.sackTimer); 286 callout_handle_init(&priv->ackp.rackTimer); 287 288 /* Done */ 289 return (0); 290 } 291 292 /* 293 * Give our OK for a hook to be added. 294 */ 295 static int 296 ng_pptpgre_newhook(node_p node, hook_p hook, const char *name) 297 { 298 const priv_p priv = NG_NODE_PRIVATE(node); 299 hook_p *hookPtr; 300 301 /* Check hook name */ 302 if (strcmp(name, NG_PPTPGRE_HOOK_UPPER) == 0) 303 hookPtr = &priv->upper; 304 else if (strcmp(name, NG_PPTPGRE_HOOK_LOWER) == 0) 305 hookPtr = &priv->lower; 306 else 307 return (EINVAL); 308 309 /* See if already connected */ 310 if (*hookPtr != NULL) 311 return (EISCONN); 312 313 /* OK */ 314 *hookPtr = hook; 315 return (0); 316 } 317 318 /* 319 * Receive a control message. 320 */ 321 static int 322 ng_pptpgre_rcvmsg(node_p node, item_p item, hook_p lasthook) 323 { 324 const priv_p priv = NG_NODE_PRIVATE(node); 325 struct ng_mesg *resp = NULL; 326 int error = 0; 327 struct ng_mesg *msg; 328 329 NGI_GET_MSG(item, msg); 330 switch (msg->header.typecookie) { 331 case NGM_PPTPGRE_COOKIE: 332 switch (msg->header.cmd) { 333 case NGM_PPTPGRE_SET_CONFIG: 334 { 335 struct ng_pptpgre_conf *const newConf = 336 (struct ng_pptpgre_conf *) msg->data; 337 338 /* Check for invalid or illegal config */ 339 if (msg->header.arglen != sizeof(*newConf)) 340 ERROUT(EINVAL); 341 ng_pptpgre_reset(node); /* reset on configure */ 342 priv->conf = *newConf; 343 break; 344 } 345 case NGM_PPTPGRE_GET_CONFIG: 346 NG_MKRESPONSE(resp, msg, sizeof(priv->conf), M_NOWAIT); 347 if (resp == NULL) 348 ERROUT(ENOMEM); 349 bcopy(&priv->conf, resp->data, sizeof(priv->conf)); 350 break; 351 case NGM_PPTPGRE_GET_STATS: 352 case NGM_PPTPGRE_CLR_STATS: 353 case NGM_PPTPGRE_GETCLR_STATS: 354 { 355 if (msg->header.cmd != NGM_PPTPGRE_CLR_STATS) { 356 NG_MKRESPONSE(resp, msg, 357 sizeof(priv->stats), M_NOWAIT); 358 if (resp == NULL) 359 ERROUT(ENOMEM); 360 bcopy(&priv->stats, 361 resp->data, sizeof(priv->stats)); 362 } 363 if (msg->header.cmd != NGM_PPTPGRE_GET_STATS) 364 bzero(&priv->stats, sizeof(priv->stats)); 365 break; 366 } 367 default: 368 error = EINVAL; 369 break; 370 } 371 break; 372 default: 373 error = EINVAL; 374 break; 375 } 376 done: 377 NG_RESPOND_MSG(error, node, item, resp); 378 NG_FREE_MSG(msg); 379 return (error); 380 } 381 382 /* 383 * Receive incoming data on a hook. 384 */ 385 static int 386 ng_pptpgre_rcvdata(hook_p hook, item_p item) 387 { 388 const node_p node = NG_HOOK_NODE(hook); 389 const priv_p priv = NG_NODE_PRIVATE(node); 390 391 /* If not configured, reject */ 392 if (!priv->conf.enabled) { 393 NG_FREE_ITEM(item); 394 return (ENXIO); 395 } 396 397 /* Treat as xmit or recv data */ 398 if (hook == priv->upper) 399 return ng_pptpgre_xmit(node, item); 400 if (hook == priv->lower) 401 return ng_pptpgre_recv(node, item); 402 panic("%s: weird hook", __func__); 403 } 404 405 /* 406 * Destroy node 407 */ 408 static int 409 ng_pptpgre_shutdown(node_p node) 410 { 411 const priv_p priv = NG_NODE_PRIVATE(node); 412 413 /* Reset node */ 414 ng_pptpgre_reset(node); 415 416 /* Take down netgraph node */ 417 bzero(priv, sizeof(*priv)); 418 FREE(priv, M_NETGRAPH); 419 NG_NODE_SET_PRIVATE(node, NULL); 420 NG_NODE_UNREF(node); 421 return (0); 422 } 423 424 /* 425 * Hook disconnection 426 */ 427 static int 428 ng_pptpgre_disconnect(hook_p hook) 429 { 430 const node_p node = NG_HOOK_NODE(hook); 431 const priv_p priv = NG_NODE_PRIVATE(node); 432 433 /* Zero out hook pointer */ 434 if (hook == priv->upper) 435 priv->upper = NULL; 436 else if (hook == priv->lower) 437 priv->lower = NULL; 438 else 439 panic("%s: unknown hook", __func__); 440 441 /* Go away if no longer connected to anything */ 442 if ((NG_NODE_NUMHOOKS(node) == 0) 443 && (NG_NODE_IS_VALID(node))) 444 ng_rmnode_self(node); 445 return (0); 446 } 447 448 /************************************************************************* 449 TRANSMIT AND RECEIVE FUNCTIONS 450 *************************************************************************/ 451 452 /* 453 * Transmit an outgoing frame, or just an ack if m is NULL. 454 */ 455 static int 456 ng_pptpgre_xmit(node_p node, item_p item) 457 { 458 const priv_p priv = NG_NODE_PRIVATE(node); 459 struct ng_pptpgre_ackp *const a = &priv->ackp; 460 u_char buf[sizeof(struct greheader) + 2 * sizeof(u_int32_t)]; 461 struct greheader *const gre = (struct greheader *)buf; 462 int grelen, error; 463 struct mbuf *m; 464 465 if (item) { 466 NGI_GET_M(item, m); 467 } else { 468 m = NULL; 469 } 470 /* Check if there's data */ 471 if (m != NULL) { 472 473 /* Is our transmit window full? */ 474 if ((u_int32_t)PPTP_SEQ_DIFF(priv->xmitSeq, priv->recvAck) 475 >= a->xmitWin) { 476 priv->stats.xmitDrops++; 477 NG_FREE_M(m); 478 NG_FREE_ITEM(item); 479 return (ENOBUFS); 480 } 481 482 /* Sanity check frame length */ 483 if (m != NULL && m->m_pkthdr.len > PPTP_MAX_PAYLOAD) { 484 priv->stats.xmitTooBig++; 485 NG_FREE_M(m); 486 NG_FREE_ITEM(item); 487 return (EMSGSIZE); 488 } 489 } else { 490 priv->stats.xmitLoneAcks++; 491 } 492 493 /* Build GRE header */ 494 ((u_int32_t *)gre)[0] = htonl(PPTP_INIT_VALUE); 495 gre->length = (m != NULL) ? htons((u_short)m->m_pkthdr.len) : 0; 496 gre->cid = htons(priv->conf.peerCid); 497 498 /* Include sequence number if packet contains any data */ 499 if (m != NULL) { 500 gre->hasSeq = 1; 501 a->timeSent[priv->xmitSeq - priv->recvAck] 502 = ng_pptpgre_time(node); 503 priv->xmitSeq++; 504 gre->data[0] = htonl(priv->xmitSeq); 505 } 506 507 /* Include acknowledgement (and stop send ack timer) if needed */ 508 if (priv->conf.enableAlwaysAck || priv->xmitAck != priv->recvSeq) { 509 gre->hasAck = 1; 510 gre->data[gre->hasSeq] = htonl(priv->recvSeq); 511 priv->xmitAck = priv->recvSeq; 512 a->sackTimerPtr = NULL; /* "stop" timer */ 513 } 514 515 /* Prepend GRE header to outgoing frame */ 516 grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck); 517 if (m == NULL) { 518 MGETHDR(m, M_DONTWAIT, MT_DATA); 519 if (m == NULL) { 520 priv->stats.memoryFailures++; 521 if (item) 522 NG_FREE_ITEM(item); 523 return (ENOBUFS); 524 } 525 m->m_len = m->m_pkthdr.len = grelen; 526 m->m_pkthdr.rcvif = NULL; 527 } else { 528 M_PREPEND(m, grelen, M_NOWAIT); 529 if (m == NULL || (m->m_len < grelen 530 && (m = m_pullup(m, grelen)) == NULL)) { 531 priv->stats.memoryFailures++; 532 if (item) 533 NG_FREE_ITEM(item); 534 return (ENOBUFS); 535 } 536 } 537 bcopy(gre, mtod(m, u_char *), grelen); 538 539 /* Update stats */ 540 priv->stats.xmitPackets++; 541 priv->stats.xmitOctets += m->m_pkthdr.len; 542 543 /* Deliver packet */ 544 if (item) { 545 NG_FWD_NEW_DATA(error, item, priv->lower, m); 546 } else { 547 NG_SEND_DATA_ONLY(error, priv->lower, m); 548 } 549 550 551 /* Start receive ACK timer if data was sent and not already running */ 552 if (error == 0 && gre->hasSeq && priv->xmitSeq == priv->recvAck + 1) 553 ng_pptpgre_start_recv_ack_timer(node); 554 return (error); 555 } 556 557 /* 558 * Handle an incoming packet. The packet includes the IP header. 559 */ 560 static int 561 ng_pptpgre_recv(node_p node, item_p item) 562 { 563 const priv_p priv = NG_NODE_PRIVATE(node); 564 int iphlen, grelen, extralen; 565 struct greheader *gre; 566 struct ip *ip; 567 int error = 0; 568 struct mbuf *m; 569 570 NGI_GET_M(item, m); 571 /* Update stats */ 572 priv->stats.recvPackets++; 573 priv->stats.recvOctets += m->m_pkthdr.len; 574 575 /* Sanity check packet length */ 576 if (m->m_pkthdr.len < sizeof(*ip) + sizeof(*gre)) { 577 priv->stats.recvRunts++; 578 bad: 579 NG_FREE_M(m); 580 NG_FREE_ITEM(item); 581 return (EINVAL); 582 } 583 584 /* Safely pull up the complete IP+GRE headers */ 585 if (m->m_len < sizeof(*ip) + sizeof(*gre) 586 && (m = m_pullup(m, sizeof(*ip) + sizeof(*gre))) == NULL) { 587 priv->stats.memoryFailures++; 588 NG_FREE_ITEM(item); 589 return (ENOBUFS); 590 } 591 ip = mtod(m, struct ip *); 592 iphlen = ip->ip_hl << 2; 593 if (m->m_len < iphlen + sizeof(*gre)) { 594 if ((m = m_pullup(m, iphlen + sizeof(*gre))) == NULL) { 595 priv->stats.memoryFailures++; 596 NG_FREE_ITEM(item); 597 return (ENOBUFS); 598 } 599 ip = mtod(m, struct ip *); 600 } 601 gre = (struct greheader *)((u_char *)ip + iphlen); 602 grelen = sizeof(*gre) + sizeof(u_int32_t) * (gre->hasSeq + gre->hasAck); 603 if (m->m_pkthdr.len < iphlen + grelen) { 604 priv->stats.recvRunts++; 605 goto bad; 606 } 607 if (m->m_len < iphlen + grelen) { 608 if ((m = m_pullup(m, iphlen + grelen)) == NULL) { 609 priv->stats.memoryFailures++; 610 NG_FREE_ITEM(item); 611 return (ENOBUFS); 612 } 613 ip = mtod(m, struct ip *); 614 gre = (struct greheader *)((u_char *)ip + iphlen); 615 } 616 617 /* Sanity check packet length and GRE header bits */ 618 extralen = m->m_pkthdr.len 619 - (iphlen + grelen + (u_int16_t)ntohs(gre->length)); 620 if (extralen < 0) { 621 priv->stats.recvBadGRE++; 622 goto bad; 623 } 624 if ((ntohl(*((u_int32_t *)gre)) & PPTP_INIT_MASK) != PPTP_INIT_VALUE) { 625 priv->stats.recvBadGRE++; 626 goto bad; 627 } 628 if (ntohs(gre->cid) != priv->conf.cid) { 629 priv->stats.recvBadCID++; 630 goto bad; 631 } 632 633 /* Look for peer ack */ 634 if (gre->hasAck) { 635 struct ng_pptpgre_ackp *const a = &priv->ackp; 636 const u_int32_t ack = ntohl(gre->data[gre->hasSeq]); 637 const int index = ack - priv->recvAck - 1; 638 long sample; 639 long diff; 640 641 /* Sanity check ack value */ 642 if (PPTP_SEQ_DIFF(ack, priv->xmitSeq) > 0) { 643 priv->stats.recvBadAcks++; 644 goto badAck; /* we never sent it! */ 645 } 646 if (PPTP_SEQ_DIFF(ack, priv->recvAck) <= 0) 647 goto badAck; /* ack already timed out */ 648 priv->recvAck = ack; 649 650 /* Update adaptive timeout stuff */ 651 sample = ng_pptpgre_time(node) - a->timeSent[index]; 652 diff = sample - a->rtt; 653 a->rtt += PPTP_ACK_ALPHA(diff); 654 if (diff < 0) 655 diff = -diff; 656 a->dev += PPTP_ACK_BETA(diff - a->dev); 657 a->ato = a->rtt + PPTP_ACK_CHI(a->dev); 658 if (a->ato > PPTP_MAX_TIMEOUT) 659 a->ato = PPTP_MAX_TIMEOUT; 660 if (a->ato < PPTP_MIN_TIMEOUT) 661 a->ato = PPTP_MIN_TIMEOUT; 662 663 /* Shift packet transmit times in our transmit window */ 664 ovbcopy(a->timeSent + index + 1, a->timeSent, 665 sizeof(*a->timeSent) * (PPTP_XMIT_WIN - (index + 1))); 666 667 /* If we sent an entire window, increase window size by one */ 668 if (PPTP_SEQ_DIFF(ack, a->winAck) >= 0 669 && a->xmitWin < PPTP_XMIT_WIN) { 670 a->xmitWin++; 671 a->winAck = ack + a->xmitWin; 672 } 673 674 /* Stop/(re)start receive ACK timer as necessary */ 675 a->rackTimerPtr = NULL; 676 if (priv->recvAck != priv->xmitSeq) 677 ng_pptpgre_start_recv_ack_timer(node); 678 } 679 badAck: 680 681 /* See if frame contains any data */ 682 if (gre->hasSeq) { 683 struct ng_pptpgre_ackp *const a = &priv->ackp; 684 const u_int32_t seq = ntohl(gre->data[0]); 685 686 /* Sanity check sequence number */ 687 if (PPTP_SEQ_DIFF(seq, priv->recvSeq) <= 0) { 688 if (seq == priv->recvSeq) 689 priv->stats.recvDuplicates++; 690 else 691 priv->stats.recvOutOfOrder++; 692 goto bad; /* out-of-order or dup */ 693 } 694 priv->recvSeq = seq; 695 696 /* We need to acknowledge this packet; do it soon... */ 697 if (a->sackTimerPtr == NULL) { 698 int maxWait; 699 700 /* Take 1/4 of the estimated round trip time */ 701 maxWait = (a->rtt >> 2); 702 703 /* If delayed ACK is disabled, send it now */ 704 if (!priv->conf.enableDelayedAck 705 || maxWait < PPTP_MIN_ACK_DELAY) 706 ng_pptpgre_xmit(node, NULL); 707 else { /* send the ack later */ 708 if (maxWait > PPTP_MAX_ACK_DELAY) 709 maxWait = PPTP_MAX_ACK_DELAY; 710 ng_pptpgre_start_send_ack_timer(node, maxWait); 711 } 712 } 713 714 /* Trim mbuf down to internal payload */ 715 m_adj(m, iphlen + grelen); 716 if (extralen > 0) 717 m_adj(m, -extralen); 718 719 /* Deliver frame to upper layers */ 720 NG_FWD_NEW_DATA(error, item, priv->upper, m); 721 } else { 722 priv->stats.recvLoneAcks++; 723 NG_FREE_ITEM(item); 724 NG_FREE_M(m); /* no data to deliver */ 725 } 726 return (error); 727 } 728 729 /************************************************************************* 730 TIMER RELATED FUNCTIONS 731 *************************************************************************/ 732 733 /* 734 * Start a timer for the peer's acknowledging our oldest unacknowledged 735 * sequence number. If we get an ack for this sequence number before 736 * the timer goes off, we cancel the timer. Resets currently running 737 * recv ack timer, if any. 738 */ 739 static void 740 ng_pptpgre_start_recv_ack_timer(node_p node) 741 { 742 const priv_p priv = NG_NODE_PRIVATE(node); 743 struct ng_pptpgre_ackp *const a = &priv->ackp; 744 int remain, ticks; 745 746 /* Compute how long until oldest unack'd packet times out, 747 and reset the timer to that time. */ 748 KASSERT(a->rackTimerPtr == NULL, ("%s: rackTimer", __func__)); 749 remain = (a->timeSent[0] + a->ato) - ng_pptpgre_time(node); 750 if (remain < 0) 751 remain = 0; 752 #ifdef DEBUG_RAT 753 a->timerLength = remain; 754 a->timerStart = ng_pptpgre_time(node); 755 #endif 756 757 /* Start new timer */ 758 MALLOC(a->rackTimerPtr, node_p *, sizeof(node_p), M_NETGRAPH, M_NOWAIT); 759 if (a->rackTimerPtr == NULL) { 760 priv->stats.memoryFailures++; 761 return; /* XXX potential hang here */ 762 } 763 *a->rackTimerPtr = node; /* insures the correct timeout event */ 764 NG_NODE_REF(node); 765 766 /* Be conservative: timeout() can return up to 1 tick early */ 767 ticks = (((remain * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE) + 1; 768 a->rackTimer = timeout(ng_pptpgre_recv_ack_timeout, 769 a->rackTimerPtr, ticks); 770 } 771 772 /* 773 * The peer has failed to acknowledge the oldest unacknowledged sequence 774 * number within the time allotted. Update our adaptive timeout parameters 775 * and reset/restart the recv ack timer. 776 */ 777 static void 778 ng_pptpgre_recv_ack_timeout(void *arg) 779 { 780 int s = splnet(); 781 const node_p node = *((node_p *)arg); 782 const priv_p priv = NG_NODE_PRIVATE(node); 783 struct ng_pptpgre_ackp *const a = &priv->ackp; 784 785 /* This complicated stuff is needed to avoid race conditions */ 786 FREE(arg, M_NETGRAPH); 787 KASSERT(node->nd_refs > 0, ("%s: no nd_refs", __func__)); 788 if (NG_NODE_NOT_VALID(node)) { /* shutdown race condition */ 789 NG_NODE_UNREF(node); 790 splx(s); 791 return; 792 } 793 if (arg != a->rackTimerPtr) { /* timer stopped race condition */ 794 NG_NODE_UNREF(node); 795 splx(s); 796 return; 797 } 798 a->rackTimerPtr = NULL; 799 800 /* Update adaptive timeout stuff */ 801 priv->stats.recvAckTimeouts++; 802 a->rtt = PPTP_ACK_DELTA(a->rtt); 803 a->ato = a->rtt + PPTP_ACK_CHI(a->dev); 804 if (a->ato > PPTP_MAX_TIMEOUT) 805 a->ato = PPTP_MAX_TIMEOUT; 806 if (a->ato < PPTP_MIN_TIMEOUT) 807 a->ato = PPTP_MIN_TIMEOUT; 808 809 #ifdef DEBUG_RAT 810 log(LOG_DEBUG, 811 "RAT now=%d seq=0x%x sent=%d tstart=%d tlen=%d ato=%d\n", 812 (int)ng_pptpgre_time(node), priv->recvAck + 1, 813 (int)a->timeSent[0], (int)a->timerStart, (int)a->timerLength, a->ato); 814 #endif 815 816 /* Reset ack and sliding window */ 817 priv->recvAck = priv->xmitSeq; /* pretend we got the ack */ 818 a->xmitWin = (a->xmitWin + 1) / 2; /* shrink transmit window */ 819 a->winAck = priv->recvAck + a->xmitWin; /* reset win expand time */ 820 NG_NODE_UNREF(node); 821 splx(s); 822 } 823 824 /* 825 * Start the send ack timer. This assumes the timer is not 826 * already running. 827 */ 828 static void 829 ng_pptpgre_start_send_ack_timer(node_p node, int ackTimeout) 830 { 831 const priv_p priv = NG_NODE_PRIVATE(node); 832 struct ng_pptpgre_ackp *const a = &priv->ackp; 833 int ticks; 834 835 /* Start new timer */ 836 KASSERT(a->sackTimerPtr == NULL, ("%s: sackTimer", __func__)); 837 MALLOC(a->sackTimerPtr, node_p *, sizeof(node_p), M_NETGRAPH, M_NOWAIT); 838 if (a->sackTimerPtr == NULL) { 839 priv->stats.memoryFailures++; 840 return; /* XXX potential hang here */ 841 } 842 *a->sackTimerPtr = node; 843 NG_NODE_REF(node); 844 845 /* Be conservative: timeout() can return up to 1 tick early */ 846 ticks = (((ackTimeout * hz) + PPTP_TIME_SCALE - 1) / PPTP_TIME_SCALE); 847 a->sackTimer = timeout(ng_pptpgre_send_ack_timeout, 848 a->sackTimerPtr, ticks); 849 } 850 851 /* 852 * We've waited as long as we're willing to wait before sending an 853 * acknowledgement to the peer for received frames. We had hoped to 854 * be able to piggy back our acknowledgement on an outgoing data frame, 855 * but apparently there haven't been any since. So send the ack now. 856 */ 857 static void 858 ng_pptpgre_send_ack_timeout(void *arg) 859 { 860 int s = splnet(); 861 const node_p node = *((node_p *)arg); 862 const priv_p priv = NG_NODE_PRIVATE(node); 863 struct ng_pptpgre_ackp *const a = &priv->ackp; 864 865 /* This complicated stuff is needed to avoid race conditions */ 866 FREE(arg, M_NETGRAPH); 867 KASSERT(node->nd_refs > 0, ("%s: no nd_refs", __func__)); 868 if (NG_NODE_NOT_VALID(node)) { /* shutdown race condition */ 869 NG_NODE_UNREF(node); 870 splx(s); 871 return; 872 } 873 if (a->sackTimerPtr != arg) { /* timer stopped race condition */ 874 NG_NODE_UNREF(node); 875 splx(s); 876 return; 877 } 878 a->sackTimerPtr = NULL; 879 880 /* Send a frame with an ack but no payload */ 881 ng_pptpgre_xmit(node, NULL); 882 NG_NODE_UNREF(node); 883 splx(s); 884 } 885 886 /************************************************************************* 887 MISC FUNCTIONS 888 *************************************************************************/ 889 890 /* 891 * Reset state 892 */ 893 static void 894 ng_pptpgre_reset(node_p node) 895 { 896 const priv_p priv = NG_NODE_PRIVATE(node); 897 struct ng_pptpgre_ackp *const a = &priv->ackp; 898 899 /* Reset adaptive timeout state */ 900 a->ato = PPTP_MAX_TIMEOUT; 901 a->rtt = priv->conf.peerPpd * PPTP_TIME_SCALE / 10; /* ppd in 10ths */ 902 if (a->rtt < PPTP_MIN_RTT) 903 a->rtt = PPTP_MIN_RTT; 904 a->dev = 0; 905 a->xmitWin = (priv->conf.recvWin + 1) / 2; 906 if (a->xmitWin < 2) /* often the first packet is lost */ 907 a->xmitWin = 2; /* because the peer isn't ready */ 908 if (a->xmitWin > PPTP_XMIT_WIN) 909 a->xmitWin = PPTP_XMIT_WIN; 910 a->winAck = a->xmitWin; 911 912 /* Reset sequence numbers */ 913 priv->recvSeq = ~0; 914 priv->recvAck = ~0; 915 priv->xmitSeq = ~0; 916 priv->xmitAck = ~0; 917 918 /* Reset start time */ 919 getmicrouptime(&priv->startTime); 920 921 /* Reset stats */ 922 bzero(&priv->stats, sizeof(priv->stats)); 923 924 /* "Stop" timers */ 925 a->sackTimerPtr = NULL; 926 a->rackTimerPtr = NULL; 927 } 928 929 /* 930 * Return the current time scaled & translated to our internally used format. 931 */ 932 static pptptime_t 933 ng_pptpgre_time(node_p node) 934 { 935 const priv_p priv = NG_NODE_PRIVATE(node); 936 struct timeval tv; 937 pptptime_t t; 938 939 microuptime(&tv); 940 if (tv.tv_sec < priv->startTime.tv_sec 941 || (tv.tv_sec == priv->startTime.tv_sec 942 && tv.tv_usec < priv->startTime.tv_usec)) 943 return (0); 944 timevalsub(&tv, &priv->startTime); 945 t = (pptptime_t)tv.tv_sec * PPTP_TIME_SCALE; 946 t += (pptptime_t)tv.tv_usec / (1000000 / PPTP_TIME_SCALE); 947 return(t); 948 } 949 950