161861Sru/* 261861Sru * alias_pptp.c 361861Sru * 461861Sru * Copyright (c) 2000 Whistle Communications, Inc. 561861Sru * All rights reserved. 661861Sru * 761861Sru * Subject to the following obligations and disclaimer of warranty, use and 861861Sru * redistribution of this software, in source or object code forms, with or 961861Sru * without modifications are expressly permitted by Whistle Communications; 1061861Sru * provided, however, that: 1161861Sru * 1. Any and all reproductions of the source or object code must include the 1261861Sru * copyright notice above and the following disclaimer of warranties; and 1361861Sru * 2. No rights are granted, in any manner or form, to use Whistle 1461861Sru * Communications, Inc. trademarks, including the mark "WHISTLE 1561861Sru * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 1661861Sru * such appears in the above copyright notice or in the software. 1761861Sru * 1861861Sru * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 1961861Sru * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 2061861Sru * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 2161861Sru * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 2261861Sru * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 2361861Sru * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 2461861Sru * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 2561861Sru * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 2661861Sru * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 2761861Sru * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 2861861Sru * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 2961861Sru * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 3061861Sru * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 3161861Sru * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3261861Sru * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 3361861Sru * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 3461861Sru * OF SUCH DAMAGE. 3561861Sru * 3661861Sru * Author: Erik Salander <erik@whistle.com> 3761861Sru */ 3861861Sru 3984195Sdillon#include <sys/cdefs.h> 4084195Sdillon__FBSDID("$FreeBSD: releng/10.3/sys/netinet/libalias/alias_pptp.c 190841 2009-04-08 11:56:49Z piso $"); 4184195Sdillon 42162674Spiso/* Includes */ 43162674Spiso#ifdef _KERNEL 44162674Spiso#include <sys/param.h> 45162674Spiso#include <sys/limits.h> 46162674Spiso#include <sys/kernel.h> 47162674Spiso#include <sys/module.h> 48162674Spiso#else 49162674Spiso#include <errno.h> 50162674Spiso#include <limits.h> 51162674Spiso#include <sys/types.h> 52162674Spiso#include <stdio.h> 53162674Spiso#endif 54162674Spiso 55162674Spiso#include <netinet/tcp.h> 56162674Spiso 57162674Spiso#ifdef _KERNEL 58162674Spiso#include <netinet/libalias/alias.h> 59162674Spiso#include <netinet/libalias/alias_local.h> 60162674Spiso#include <netinet/libalias/alias_mod.h> 61162674Spiso#else 62162674Spiso#include "alias.h" 63162674Spiso#include "alias_local.h" 64162674Spiso#include "alias_mod.h" 65162674Spiso#endif 66162674Spiso 67162674Spiso#define PPTP_CONTROL_PORT_NUMBER 1723 68162674Spiso 69162674Spisostatic void 70162674SpisoAliasHandlePptpOut(struct libalias *, struct ip *, struct alias_link *); 71162674Spiso 72162674Spisostatic void 73162674SpisoAliasHandlePptpIn(struct libalias *, struct ip *, struct alias_link *); 74162674Spiso 75162674Spisostatic int 76162674SpisoAliasHandlePptpGreOut(struct libalias *, struct ip *); 77162674Spiso 78162674Spisostatic int 79162674SpisoAliasHandlePptpGreIn(struct libalias *, struct ip *); 80162674Spiso 81162674Spisostatic int 82190841Spisofingerprint(struct libalias *la, struct alias_data *ah) 83162674Spiso{ 84162674Spiso 85162674Spiso if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL) 86162674Spiso return (-1); 87162674Spiso if (ntohs(*ah->dport) == PPTP_CONTROL_PORT_NUMBER 88162674Spiso || ntohs(*ah->sport) == PPTP_CONTROL_PORT_NUMBER) 89162674Spiso return (0); 90162674Spiso return (-1); 91162674Spiso} 92162674Spiso 93162674Spisostatic int 94190841Spisofingerprintgre(struct libalias *la, struct alias_data *ah) 95162674Spiso{ 96162674Spiso 97162674Spiso return (0); 98162674Spiso} 99162674Spiso 100162674Spisostatic int 101162674Spisoprotohandlerin(struct libalias *la, struct ip *pip, struct alias_data *ah) 102162674Spiso{ 103162674Spiso 104162674Spiso AliasHandlePptpIn(la, pip, ah->lnk); 105162674Spiso return (0); 106162674Spiso} 107162674Spiso 108162674Spisostatic int 109162674Spisoprotohandlerout(struct libalias *la, struct ip *pip, struct alias_data *ah) 110162674Spiso{ 111162674Spiso 112162674Spiso AliasHandlePptpOut(la, pip, ah->lnk); 113162674Spiso return (0); 114162674Spiso} 115162674Spiso 116162674Spisostatic int 117162674Spisoprotohandlergrein(struct libalias *la, struct ip *pip, struct alias_data *ah) 118162674Spiso{ 119162674Spiso 120162674Spiso if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY || 121162674Spiso AliasHandlePptpGreIn(la, pip) == 0) 122162674Spiso return (0); 123162674Spiso return (-1); 124162674Spiso} 125162674Spiso 126162674Spisostatic int 127162674Spisoprotohandlergreout(struct libalias *la, struct ip *pip, struct alias_data *ah) 128162674Spiso{ 129162674Spiso 130162674Spiso if (AliasHandlePptpGreOut(la, pip) == 0) 131162674Spiso return (0); 132162674Spiso return (-1); 133162674Spiso} 134162674Spiso 135162674Spiso/* Kernel module definition. */ 136162674Spisostruct proto_handler handlers[] = { 137162674Spiso { 138162674Spiso .pri = 200, 139162674Spiso .dir = IN, 140162674Spiso .proto = TCP, 141162674Spiso .fingerprint = &fingerprint, 142162674Spiso .protohandler = &protohandlerin 143162674Spiso }, 144162674Spiso { 145162674Spiso .pri = 210, 146162674Spiso .dir = OUT, 147162674Spiso .proto = TCP, 148162674Spiso .fingerprint = &fingerprint, 149162674Spiso .protohandler = &protohandlerout 150162674Spiso }, 151162674Spiso/* 152162674Spiso * WATCH OUT!!! these 2 handlers NEED a priority of INT_MAX (highest possible) 153162674Spiso * cause they will ALWAYS process packets, so they must be the last one 154162674Spiso * in chain: look fingerprintgre() above. 155162674Spiso */ 156162674Spiso { 157162674Spiso .pri = INT_MAX, 158162674Spiso .dir = IN, 159162674Spiso .proto = IP, 160162674Spiso .fingerprint = &fingerprintgre, 161162674Spiso .protohandler = &protohandlergrein 162162674Spiso }, 163162674Spiso { 164162674Spiso .pri = INT_MAX, 165162674Spiso .dir = OUT, 166162674Spiso .proto = IP, 167162674Spiso .fingerprint = &fingerprintgre, 168162674Spiso .protohandler = &protohandlergreout 169162674Spiso }, 170162674Spiso { EOH } 171162674Spiso}; 172162674Spisostatic int 173162674Spisomod_handler(module_t mod, int type, void *data) 174162674Spiso{ 175162674Spiso int error; 176162674Spiso 177162674Spiso switch (type) { 178162674Spiso case MOD_LOAD: 179162674Spiso error = 0; 180162674Spiso LibAliasAttachHandlers(handlers); 181162674Spiso break; 182162674Spiso case MOD_UNLOAD: 183162674Spiso error = 0; 184162674Spiso LibAliasDetachHandlers(handlers); 185162674Spiso break; 186162674Spiso default: 187162674Spiso error = EINVAL; 188162674Spiso } 189162674Spiso return (error); 190162674Spiso} 191162674Spiso 192162674Spiso#ifdef _KERNEL 193162674Spisostatic 194162674Spiso#endif 195162674Spisomoduledata_t alias_mod = { 196162674Spiso "alias_pptp", mod_handler, NULL 197162674Spiso}; 198162674Spiso 199162674Spiso#ifdef _KERNEL 200162674SpisoDECLARE_MODULE(alias_pptp, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND); 201162674SpisoMODULE_VERSION(alias_pptp, 1); 202162674SpisoMODULE_DEPEND(alias_pptp, libalias, 1, 1, 1); 203162674Spiso#endif 204162674Spiso 20561861Sru/* 20661861Sru Alias_pptp.c performs special processing for PPTP sessions under TCP. 20761861Sru Specifically, watch PPTP control messages and alias the Call ID or the 20861861Sru Peer's Call ID in the appropriate messages. Note, PPTP requires 20961861Sru "de-aliasing" of incoming packets, this is different than any other 21061861Sru TCP applications that are currently (ie. FTP, IRC and RTSP) aliased. 21161861Sru 21264452Sru For Call IDs encountered for the first time, a PPTP alias link is created. 21364452Sru The PPTP alias link uses the Call ID in place of the original port number. 21461861Sru An alias Call ID is created. 21561861Sru 21661861Sru For this routine to work, the PPTP control messages must fit entirely 21761861Sru into a single TCP packet. This is typically the case, but is not 21861861Sru required by the spec. 21961861Sru 22061861Sru Unlike some of the other TCP applications that are aliased (ie. FTP, 22161861Sru IRC and RTSP), the PPTP control messages that need to be aliased are 22261861Sru guaranteed to remain the same length. The aliased Call ID is a fixed 22361861Sru length field. 22461861Sru 22561861Sru Reference: RFC 2637 22661861Sru 22761861Sru Initial version: May, 2000 (eds) 22861861Sru 22961861Sru*/ 23061861Sru 23161861Sru/* 23261861Sru * PPTP definitions 23361861Sru */ 23461861Sru 235127094Sdesstruct grehdr { /* Enhanced GRE header. */ 236127094Sdes u_int16_t gh_flags; /* Flags. */ 237127094Sdes u_int16_t gh_protocol; /* Protocol type. */ 238127094Sdes u_int16_t gh_length; /* Payload length. */ 239127094Sdes u_int16_t gh_call_id; /* Call ID. */ 240127094Sdes u_int32_t gh_seq_no; /* Sequence number (optional). */ 241127094Sdes u_int32_t gh_ack_no; /* Acknowledgment number 242127094Sdes * (optional). */ 24361861Sru}; 244127094Sdestypedef struct grehdr GreHdr; 24561861Sru 24661861Sru/* The PPTP protocol ID used in the GRE 'proto' field. */ 24761861Sru#define PPTP_GRE_PROTO 0x880b 24861861Sru 24961861Sru/* Bits that must be set a certain way in all PPTP/GRE packets. */ 25061861Sru#define PPTP_INIT_VALUE ((0x2001 << 16) | PPTP_GRE_PROTO) 25161861Sru#define PPTP_INIT_MASK 0xef7fffff 25261861Sru 25361861Sru#define PPTP_MAGIC 0x1a2b3c4d 25461861Sru#define PPTP_CTRL_MSG_TYPE 1 25561861Sru 25661861Sruenum { 257127094Sdes PPTP_StartCtrlConnRequest = 1, 258127094Sdes PPTP_StartCtrlConnReply = 2, 259127094Sdes PPTP_StopCtrlConnRequest = 3, 260127094Sdes PPTP_StopCtrlConnReply = 4, 261127094Sdes PPTP_EchoRequest = 5, 262127094Sdes PPTP_EchoReply = 6, 263127094Sdes PPTP_OutCallRequest = 7, 264127094Sdes PPTP_OutCallReply = 8, 265127094Sdes PPTP_InCallRequest = 9, 266127094Sdes PPTP_InCallReply = 10, 267127094Sdes PPTP_InCallConn = 11, 268127094Sdes PPTP_CallClearRequest = 12, 269127094Sdes PPTP_CallDiscNotify = 13, 270127094Sdes PPTP_WanErrorNotify = 14, 271127094Sdes PPTP_SetLinkInfo = 15 27261861Sru}; 27361861Sru 274127094Sdes /* Message structures */ 275127094Sdesstruct pptpMsgHead { 276127094Sdes u_int16_t length; /* total length */ 277127094Sdes u_int16_t msgType;/* PPTP message type */ 278127094Sdes u_int32_t magic; /* magic cookie */ 279127094Sdes u_int16_t type; /* control message type */ 280127094Sdes u_int16_t resv0; /* reserved */ 281127094Sdes}; 282127094Sdestypedef struct pptpMsgHead *PptpMsgHead; 28361861Sru 284127094Sdesstruct pptpCodes { 285127094Sdes u_int8_t resCode;/* Result Code */ 286127094Sdes u_int8_t errCode;/* Error Code */ 287127094Sdes}; 288127094Sdestypedef struct pptpCodes *PptpCode; 28967966Sru 290127094Sdesstruct pptpCallIds { 291127094Sdes u_int16_t cid1; /* Call ID field #1 */ 292127094Sdes u_int16_t cid2; /* Call ID field #2 */ 293127094Sdes}; 294127094Sdestypedef struct pptpCallIds *PptpCallId; 29561861Sru 29661861Srustatic PptpCallId AliasVerifyPptp(struct ip *, u_int16_t *); 29761861Sru 29861861Sru 299162674Spisostatic void 300124621SphkAliasHandlePptpOut(struct libalias *la, 301127094Sdes struct ip *pip, /* IP packet to examine/patch */ 302131614Sdes struct alias_link *lnk) 303127094Sdes{ /* The PPTP control link */ 304131614Sdes struct alias_link *pptp_lnk; 305127094Sdes PptpCallId cptr; 306127094Sdes PptpCode codes; 307127094Sdes u_int16_t ctl_type; /* control message type */ 308127094Sdes struct tcphdr *tc; 30961861Sru 310127094Sdes /* Verify valid PPTP control message */ 311127094Sdes if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL) 312127094Sdes return; 31361861Sru 314127094Sdes /* Modify certain PPTP messages */ 315127094Sdes switch (ctl_type) { 316127094Sdes case PPTP_OutCallRequest: 317127094Sdes case PPTP_OutCallReply: 318127094Sdes case PPTP_InCallRequest: 319127094Sdes case PPTP_InCallReply: 320127094Sdes /* 321127094Sdes * Establish PPTP link for address and Call ID found in 322127094Sdes * control message. 323127094Sdes */ 324131614Sdes pptp_lnk = AddPptp(la, GetOriginalAddress(lnk), GetDestAddress(lnk), 325131614Sdes GetAliasAddress(lnk), cptr->cid1); 326127094Sdes break; 327127094Sdes case PPTP_CallClearRequest: 328127094Sdes case PPTP_CallDiscNotify: 329127094Sdes /* 330127094Sdes * Find PPTP link for address and Call ID found in control 331127094Sdes * message. 332127094Sdes */ 333131614Sdes pptp_lnk = FindPptpOutByCallId(la, GetOriginalAddress(lnk), 334131614Sdes GetDestAddress(lnk), 335127094Sdes cptr->cid1); 336127094Sdes break; 337127094Sdes default: 338127094Sdes return; 339127094Sdes } 34061861Sru 341131614Sdes if (pptp_lnk != NULL) { 342127094Sdes int accumulate = cptr->cid1; 34364334Sru 344127094Sdes /* alias the Call Id */ 345131614Sdes cptr->cid1 = GetAliasPort(pptp_lnk); 34661861Sru 347127094Sdes /* Compute TCP checksum for revised packet */ 348131699Sdes tc = (struct tcphdr *)ip_next(pip); 349127094Sdes accumulate -= cptr->cid1; 350127094Sdes ADJUST_CHECKSUM(accumulate, tc->th_sum); 35167966Sru 352127094Sdes switch (ctl_type) { 353127094Sdes case PPTP_OutCallReply: 354127094Sdes case PPTP_InCallReply: 355127094Sdes codes = (PptpCode) (cptr + 1); 356127094Sdes if (codes->resCode == 1) /* Connection 357127094Sdes * established, */ 358131614Sdes SetDestCallId(pptp_lnk, /* note the Peer's Call 359127094Sdes * ID. */ 360127094Sdes cptr->cid2); 361127094Sdes else 362131614Sdes SetExpire(pptp_lnk, 0); /* Connection refused. */ 363127094Sdes break; 364127094Sdes case PPTP_CallDiscNotify: /* Connection closed. */ 365131614Sdes SetExpire(pptp_lnk, 0); 366127094Sdes break; 367127094Sdes } 36867966Sru } 36961861Sru} 37061861Sru 371162674Spisostatic void 372127094SdesAliasHandlePptpIn(struct libalias *la, 373127094Sdes struct ip *pip, /* IP packet to examine/patch */ 374131614Sdes struct alias_link *lnk) 375127094Sdes{ /* The PPTP control link */ 376131614Sdes struct alias_link *pptp_lnk; 377127094Sdes PptpCallId cptr; 378127094Sdes u_int16_t *pcall_id; 379127094Sdes u_int16_t ctl_type; /* control message type */ 380127094Sdes struct tcphdr *tc; 38161861Sru 382127094Sdes /* Verify valid PPTP control message */ 383127094Sdes if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL) 384127094Sdes return; 38561861Sru 386127094Sdes /* Modify certain PPTP messages */ 387127094Sdes switch (ctl_type) { 388127094Sdes case PPTP_InCallConn: 389127094Sdes case PPTP_WanErrorNotify: 390127094Sdes case PPTP_SetLinkInfo: 391127094Sdes pcall_id = &cptr->cid1; 392127094Sdes break; 393127094Sdes case PPTP_OutCallReply: 394127094Sdes case PPTP_InCallReply: 395127094Sdes pcall_id = &cptr->cid2; 396127094Sdes break; 397127094Sdes case PPTP_CallDiscNotify: /* Connection closed. */ 398131614Sdes pptp_lnk = FindPptpInByCallId(la, GetDestAddress(lnk), 399131614Sdes GetAliasAddress(lnk), 400127094Sdes cptr->cid1); 401131614Sdes if (pptp_lnk != NULL) 402131614Sdes SetExpire(pptp_lnk, 0); 403127094Sdes return; 404127094Sdes default: 405127094Sdes return; 406127094Sdes } 40761861Sru 408127094Sdes /* Find PPTP link for address and Call ID found in PPTP Control Msg */ 409131614Sdes pptp_lnk = FindPptpInByPeerCallId(la, GetDestAddress(lnk), 410131614Sdes GetAliasAddress(lnk), 411127094Sdes *pcall_id); 41261861Sru 413131614Sdes if (pptp_lnk != NULL) { 414127094Sdes int accumulate = *pcall_id; 41564334Sru 416127094Sdes /* De-alias the Peer's Call Id. */ 417131614Sdes *pcall_id = GetOriginalPort(pptp_lnk); 41861861Sru 419127094Sdes /* Compute TCP checksum for modified packet */ 420131699Sdes tc = (struct tcphdr *)ip_next(pip); 421127094Sdes accumulate -= *pcall_id; 422127094Sdes ADJUST_CHECKSUM(accumulate, tc->th_sum); 42367966Sru 424127094Sdes if (ctl_type == PPTP_OutCallReply || ctl_type == PPTP_InCallReply) { 425127094Sdes PptpCode codes = (PptpCode) (cptr + 1); 42667966Sru 427127094Sdes if (codes->resCode == 1) /* Connection 428127094Sdes * established, */ 429131614Sdes SetDestCallId(pptp_lnk, /* note the Call ID. */ 430127094Sdes cptr->cid1); 431127094Sdes else 432131614Sdes SetExpire(pptp_lnk, 0); /* Connection refused. */ 433127094Sdes } 434127094Sdes } 43561861Sru} 43661861Sru 437127094Sdesstatic PptpCallId 438127094SdesAliasVerifyPptp(struct ip *pip, u_int16_t * ptype) 439127094Sdes{ /* IP packet to examine/patch */ 440127094Sdes int hlen, tlen, dlen; 441127094Sdes PptpMsgHead hptr; 442127094Sdes struct tcphdr *tc; 44361861Sru 444127094Sdes /* Calculate some lengths */ 445131699Sdes tc = (struct tcphdr *)ip_next(pip); 446127094Sdes hlen = (pip->ip_hl + tc->th_off) << 2; 447127094Sdes tlen = ntohs(pip->ip_len); 448127094Sdes dlen = tlen - hlen; 44961861Sru 450127094Sdes /* Verify data length */ 451131614Sdes if (dlen < (int)(sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds))) 452127094Sdes return (NULL); 45361861Sru 454127094Sdes /* Move up to PPTP message header */ 455133121Smarcus hptr = (PptpMsgHead) tcp_next(tc); 45661861Sru 457127094Sdes /* Return the control message type */ 458127094Sdes *ptype = ntohs(hptr->type); 45961861Sru 460127094Sdes /* Verify PPTP Control Message */ 461127094Sdes if ((ntohs(hptr->msgType) != PPTP_CTRL_MSG_TYPE) || 462127094Sdes (ntohl(hptr->magic) != PPTP_MAGIC)) 463127094Sdes return (NULL); 46467966Sru 465127094Sdes /* Verify data length. */ 466127094Sdes if ((*ptype == PPTP_OutCallReply || *ptype == PPTP_InCallReply) && 467131614Sdes (dlen < (int)(sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds) + 468131614Sdes sizeof(struct pptpCodes)))) 469127094Sdes return (NULL); 470127094Sdes else 471127094Sdes return (PptpCallId) (hptr + 1); 47261861Sru} 47367966Sru 474162674Spisostatic int 475124621SphkAliasHandlePptpGreOut(struct libalias *la, struct ip *pip) 47667966Sru{ 477127094Sdes GreHdr *gr; 478131614Sdes struct alias_link *lnk; 47967966Sru 480131699Sdes gr = (GreHdr *) ip_next(pip); 48167966Sru 482127094Sdes /* Check GRE header bits. */ 483127094Sdes if ((ntohl(*((u_int32_t *) gr)) & PPTP_INIT_MASK) != PPTP_INIT_VALUE) 484127094Sdes return (-1); 48567966Sru 486131614Sdes lnk = FindPptpOutByPeerCallId(la, pip->ip_src, pip->ip_dst, gr->gh_call_id); 487131614Sdes if (lnk != NULL) { 488131614Sdes struct in_addr alias_addr = GetAliasAddress(lnk); 48967966Sru 490127094Sdes /* Change source IP address. */ 491127094Sdes DifferentialChecksum(&pip->ip_sum, 492127689Sdes &alias_addr, &pip->ip_src, 2); 493127094Sdes pip->ip_src = alias_addr; 494127094Sdes } 495127094Sdes return (0); 49667966Sru} 49767966Sru 498162674Spisostatic int 499124621SphkAliasHandlePptpGreIn(struct libalias *la, struct ip *pip) 50067966Sru{ 501127094Sdes GreHdr *gr; 502131614Sdes struct alias_link *lnk; 50367966Sru 504131699Sdes gr = (GreHdr *) ip_next(pip); 50567966Sru 506127094Sdes /* Check GRE header bits. */ 507127094Sdes if ((ntohl(*((u_int32_t *) gr)) & PPTP_INIT_MASK) != PPTP_INIT_VALUE) 508127094Sdes return (-1); 50967966Sru 510131614Sdes lnk = FindPptpInByPeerCallId(la, pip->ip_src, pip->ip_dst, gr->gh_call_id); 511131614Sdes if (lnk != NULL) { 512131614Sdes struct in_addr src_addr = GetOriginalAddress(lnk); 51367966Sru 514127094Sdes /* De-alias the Peer's Call Id. */ 515131614Sdes gr->gh_call_id = GetOriginalPort(lnk); 51667966Sru 517127094Sdes /* Restore original IP address. */ 518127094Sdes DifferentialChecksum(&pip->ip_sum, 519127689Sdes &src_addr, &pip->ip_dst, 2); 520127094Sdes pip->ip_dst = src_addr; 521127094Sdes } 522127094Sdes return (0); 52367966Sru} 524