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