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