xref: /dragonfly/lib/libalias/alias_pptp.c (revision 86d7f5d3)
1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino  * alias_pptp.c
3*86d7f5d3SJohn Marino  *
4*86d7f5d3SJohn Marino  * Copyright (c) 2000 Whistle Communications, Inc.
5*86d7f5d3SJohn Marino  * All rights reserved.
6*86d7f5d3SJohn Marino  *
7*86d7f5d3SJohn Marino  * Subject to the following obligations and disclaimer of warranty, use and
8*86d7f5d3SJohn Marino  * redistribution of this software, in source or object code forms, with or
9*86d7f5d3SJohn Marino  * without modifications are expressly permitted by Whistle Communications;
10*86d7f5d3SJohn Marino  * provided, however, that:
11*86d7f5d3SJohn Marino  * 1. Any and all reproductions of the source or object code must include the
12*86d7f5d3SJohn Marino  *    copyright notice above and the following disclaimer of warranties; and
13*86d7f5d3SJohn Marino  * 2. No rights are granted, in any manner or form, to use Whistle
14*86d7f5d3SJohn Marino  *    Communications, Inc. trademarks, including the mark "WHISTLE
15*86d7f5d3SJohn Marino  *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
16*86d7f5d3SJohn Marino  *    such appears in the above copyright notice or in the software.
17*86d7f5d3SJohn Marino  *
18*86d7f5d3SJohn Marino  * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
19*86d7f5d3SJohn Marino  * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
20*86d7f5d3SJohn Marino  * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
21*86d7f5d3SJohn Marino  * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
22*86d7f5d3SJohn Marino  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
23*86d7f5d3SJohn Marino  * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
24*86d7f5d3SJohn Marino  * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
25*86d7f5d3SJohn Marino  * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
26*86d7f5d3SJohn Marino  * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
27*86d7f5d3SJohn Marino  * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
28*86d7f5d3SJohn Marino  * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
29*86d7f5d3SJohn Marino  * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
30*86d7f5d3SJohn Marino  * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
31*86d7f5d3SJohn Marino  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*86d7f5d3SJohn Marino  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
33*86d7f5d3SJohn Marino  * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
34*86d7f5d3SJohn Marino  * OF SUCH DAMAGE.
35*86d7f5d3SJohn Marino  *
36*86d7f5d3SJohn Marino  * Author: Erik Salander <erik@whistle.com>
37*86d7f5d3SJohn Marino  *
38*86d7f5d3SJohn Marino  * $FreeBSD: src/lib/libalias/alias_pptp.c,v 1.1.2.4 2001/08/01 09:52:27 obrien Exp $
39*86d7f5d3SJohn Marino  * $DragonFly: src/lib/libalias/alias_pptp.c,v 1.3 2004/08/20 00:08:17 joerg Exp $
40*86d7f5d3SJohn Marino  */
41*86d7f5d3SJohn Marino 
42*86d7f5d3SJohn Marino /*
43*86d7f5d3SJohn Marino    Alias_pptp.c performs special processing for PPTP sessions under TCP.
44*86d7f5d3SJohn Marino    Specifically, watch PPTP control messages and alias the Call ID or the
45*86d7f5d3SJohn Marino    Peer's Call ID in the appropriate messages.  Note, PPTP requires
46*86d7f5d3SJohn Marino    "de-aliasing" of incoming packets, this is different than any other
47*86d7f5d3SJohn Marino    TCP applications that are currently (ie. FTP, IRC and RTSP) aliased.
48*86d7f5d3SJohn Marino 
49*86d7f5d3SJohn Marino    For Call IDs encountered for the first time, a PPTP alias link is created.
50*86d7f5d3SJohn Marino    The PPTP alias link uses the Call ID in place of the original port number.
51*86d7f5d3SJohn Marino    An alias Call ID is created.
52*86d7f5d3SJohn Marino 
53*86d7f5d3SJohn Marino    For this routine to work, the PPTP control messages must fit entirely
54*86d7f5d3SJohn Marino    into a single TCP packet.  This is typically the case, but is not
55*86d7f5d3SJohn Marino    required by the spec.
56*86d7f5d3SJohn Marino 
57*86d7f5d3SJohn Marino    Unlike some of the other TCP applications that are aliased (ie. FTP,
58*86d7f5d3SJohn Marino    IRC and RTSP), the PPTP control messages that need to be aliased are
59*86d7f5d3SJohn Marino    guaranteed to remain the same length.  The aliased Call ID is a fixed
60*86d7f5d3SJohn Marino    length field.
61*86d7f5d3SJohn Marino 
62*86d7f5d3SJohn Marino    Reference: RFC 2637
63*86d7f5d3SJohn Marino 
64*86d7f5d3SJohn Marino    Initial version:  May, 2000 (eds)
65*86d7f5d3SJohn Marino 
66*86d7f5d3SJohn Marino */
67*86d7f5d3SJohn Marino 
68*86d7f5d3SJohn Marino /* Includes */
69*86d7f5d3SJohn Marino #include <sys/param.h>
70*86d7f5d3SJohn Marino #include <netinet/in_systm.h>
71*86d7f5d3SJohn Marino #include <netinet/in.h>
72*86d7f5d3SJohn Marino #include <netinet/ip.h>
73*86d7f5d3SJohn Marino #include <netinet/tcp.h>
74*86d7f5d3SJohn Marino 
75*86d7f5d3SJohn Marino #include <stdio.h>
76*86d7f5d3SJohn Marino 
77*86d7f5d3SJohn Marino #include "alias_local.h"
78*86d7f5d3SJohn Marino 
79*86d7f5d3SJohn Marino /*
80*86d7f5d3SJohn Marino  * PPTP definitions
81*86d7f5d3SJohn Marino  */
82*86d7f5d3SJohn Marino 
83*86d7f5d3SJohn Marino struct grehdr			/* Enhanced GRE header. */
84*86d7f5d3SJohn Marino {
85*86d7f5d3SJohn Marino     u_int16_t gh_flags;		/* Flags. */
86*86d7f5d3SJohn Marino     u_int16_t gh_protocol;	/* Protocol type. */
87*86d7f5d3SJohn Marino     u_int16_t gh_length;	/* Payload length. */
88*86d7f5d3SJohn Marino     u_int16_t gh_call_id;	/* Call ID. */
89*86d7f5d3SJohn Marino     u_int32_t gh_seq_no;	/* Sequence number (optional). */
90*86d7f5d3SJohn Marino     u_int32_t gh_ack_no;	/* Acknowledgment number (optional). */
91*86d7f5d3SJohn Marino };
92*86d7f5d3SJohn Marino typedef struct grehdr		GreHdr;
93*86d7f5d3SJohn Marino 
94*86d7f5d3SJohn Marino /* The PPTP protocol ID used in the GRE 'proto' field. */
95*86d7f5d3SJohn Marino #define PPTP_GRE_PROTO          0x880b
96*86d7f5d3SJohn Marino 
97*86d7f5d3SJohn Marino /* Bits that must be set a certain way in all PPTP/GRE packets. */
98*86d7f5d3SJohn Marino #define PPTP_INIT_VALUE		((0x2001 << 16) | PPTP_GRE_PROTO)
99*86d7f5d3SJohn Marino #define PPTP_INIT_MASK		0xef7fffff
100*86d7f5d3SJohn Marino 
101*86d7f5d3SJohn Marino #define PPTP_MAGIC		0x1a2b3c4d
102*86d7f5d3SJohn Marino #define PPTP_CTRL_MSG_TYPE	1
103*86d7f5d3SJohn Marino 
104*86d7f5d3SJohn Marino enum {
105*86d7f5d3SJohn Marino   PPTP_StartCtrlConnRequest = 1,
106*86d7f5d3SJohn Marino   PPTP_StartCtrlConnReply = 2,
107*86d7f5d3SJohn Marino   PPTP_StopCtrlConnRequest = 3,
108*86d7f5d3SJohn Marino   PPTP_StopCtrlConnReply = 4,
109*86d7f5d3SJohn Marino   PPTP_EchoRequest = 5,
110*86d7f5d3SJohn Marino   PPTP_EchoReply = 6,
111*86d7f5d3SJohn Marino   PPTP_OutCallRequest = 7,
112*86d7f5d3SJohn Marino   PPTP_OutCallReply = 8,
113*86d7f5d3SJohn Marino   PPTP_InCallRequest = 9,
114*86d7f5d3SJohn Marino   PPTP_InCallReply = 10,
115*86d7f5d3SJohn Marino   PPTP_InCallConn = 11,
116*86d7f5d3SJohn Marino   PPTP_CallClearRequest = 12,
117*86d7f5d3SJohn Marino   PPTP_CallDiscNotify = 13,
118*86d7f5d3SJohn Marino   PPTP_WanErrorNotify = 14,
119*86d7f5d3SJohn Marino   PPTP_SetLinkInfo = 15
120*86d7f5d3SJohn Marino };
121*86d7f5d3SJohn Marino 
122*86d7f5d3SJohn Marino   /* Message structures */
123*86d7f5d3SJohn Marino   struct pptpMsgHead {
124*86d7f5d3SJohn Marino     u_int16_t   length;         /* total length */
125*86d7f5d3SJohn Marino     u_int16_t   msgType;        /* PPTP message type */
126*86d7f5d3SJohn Marino     u_int32_t   magic;          /* magic cookie */
127*86d7f5d3SJohn Marino     u_int16_t   type;           /* control message type */
128*86d7f5d3SJohn Marino     u_int16_t   resv0;          /* reserved */
129*86d7f5d3SJohn Marino   };
130*86d7f5d3SJohn Marino   typedef struct pptpMsgHead    *PptpMsgHead;
131*86d7f5d3SJohn Marino 
132*86d7f5d3SJohn Marino   struct pptpCodes {
133*86d7f5d3SJohn Marino     u_int8_t    resCode;        /* Result Code */
134*86d7f5d3SJohn Marino     u_int8_t    errCode;        /* Error Code */
135*86d7f5d3SJohn Marino   };
136*86d7f5d3SJohn Marino   typedef struct pptpCodes      *PptpCode;
137*86d7f5d3SJohn Marino 
138*86d7f5d3SJohn Marino   struct pptpCallIds {
139*86d7f5d3SJohn Marino     u_int16_t   cid1;           /* Call ID field #1 */
140*86d7f5d3SJohn Marino     u_int16_t   cid2;           /* Call ID field #2 */
141*86d7f5d3SJohn Marino   };
142*86d7f5d3SJohn Marino   typedef struct pptpCallIds    *PptpCallId;
143*86d7f5d3SJohn Marino 
144*86d7f5d3SJohn Marino static PptpCallId AliasVerifyPptp(struct ip *, u_int16_t *);
145*86d7f5d3SJohn Marino 
146*86d7f5d3SJohn Marino 
147*86d7f5d3SJohn Marino void
AliasHandlePptpOut(struct ip * pip,struct alias_link * link)148*86d7f5d3SJohn Marino AliasHandlePptpOut(struct ip *pip,	    /* IP packet to examine/patch */
149*86d7f5d3SJohn Marino                    struct alias_link *link) /* The PPTP control link */
150*86d7f5d3SJohn Marino {
151*86d7f5d3SJohn Marino     struct alias_link   *pptp_link;
152*86d7f5d3SJohn Marino     PptpCallId    	cptr;
153*86d7f5d3SJohn Marino     PptpCode            codes;
154*86d7f5d3SJohn Marino     u_int16_t           ctl_type;           /* control message type */
155*86d7f5d3SJohn Marino     struct tcphdr 	*tc;
156*86d7f5d3SJohn Marino 
157*86d7f5d3SJohn Marino     /* Verify valid PPTP control message */
158*86d7f5d3SJohn Marino     if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL)
159*86d7f5d3SJohn Marino       return;
160*86d7f5d3SJohn Marino 
161*86d7f5d3SJohn Marino     /* Modify certain PPTP messages */
162*86d7f5d3SJohn Marino     switch (ctl_type) {
163*86d7f5d3SJohn Marino     case PPTP_OutCallRequest:
164*86d7f5d3SJohn Marino     case PPTP_OutCallReply:
165*86d7f5d3SJohn Marino     case PPTP_InCallRequest:
166*86d7f5d3SJohn Marino     case PPTP_InCallReply:
167*86d7f5d3SJohn Marino 	/* Establish PPTP link for address and Call ID found in control message. */
168*86d7f5d3SJohn Marino 	pptp_link = AddPptp(GetOriginalAddress(link), GetDestAddress(link),
169*86d7f5d3SJohn Marino 			    GetAliasAddress(link), cptr->cid1);
170*86d7f5d3SJohn Marino 	break;
171*86d7f5d3SJohn Marino     case PPTP_CallClearRequest:
172*86d7f5d3SJohn Marino     case PPTP_CallDiscNotify:
173*86d7f5d3SJohn Marino 	/* Find PPTP link for address and Call ID found in control message. */
174*86d7f5d3SJohn Marino 	pptp_link = FindPptpOutByCallId(GetOriginalAddress(link),
175*86d7f5d3SJohn Marino 					GetDestAddress(link),
176*86d7f5d3SJohn Marino 					cptr->cid1);
177*86d7f5d3SJohn Marino 	break;
178*86d7f5d3SJohn Marino     default:
179*86d7f5d3SJohn Marino 	return;
180*86d7f5d3SJohn Marino     }
181*86d7f5d3SJohn Marino 
182*86d7f5d3SJohn Marino       if (pptp_link != NULL) {
183*86d7f5d3SJohn Marino 	int accumulate = cptr->cid1;
184*86d7f5d3SJohn Marino 
185*86d7f5d3SJohn Marino 	/* alias the Call Id */
186*86d7f5d3SJohn Marino 	cptr->cid1 = GetAliasPort(pptp_link);
187*86d7f5d3SJohn Marino 
188*86d7f5d3SJohn Marino 	/* Compute TCP checksum for revised packet */
189*86d7f5d3SJohn Marino 	tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
190*86d7f5d3SJohn Marino 	accumulate -= cptr->cid1;
191*86d7f5d3SJohn Marino 	ADJUST_CHECKSUM(accumulate, tc->th_sum);
192*86d7f5d3SJohn Marino 
193*86d7f5d3SJohn Marino 	switch (ctl_type) {
194*86d7f5d3SJohn Marino 	case PPTP_OutCallReply:
195*86d7f5d3SJohn Marino 	case PPTP_InCallReply:
196*86d7f5d3SJohn Marino 	    codes = (PptpCode)(cptr + 1);
197*86d7f5d3SJohn Marino 	    if (codes->resCode == 1)		/* Connection established, */
198*86d7f5d3SJohn Marino 		SetDestCallId(pptp_link,	/* note the Peer's Call ID. */
199*86d7f5d3SJohn Marino 			      cptr->cid2);
200*86d7f5d3SJohn Marino 	    else
201*86d7f5d3SJohn Marino 		SetExpire(pptp_link, 0);	/* Connection refused. */
202*86d7f5d3SJohn Marino 	    break;
203*86d7f5d3SJohn Marino 	case PPTP_CallDiscNotify:		/* Connection closed. */
204*86d7f5d3SJohn Marino 	    SetExpire(pptp_link, 0);
205*86d7f5d3SJohn Marino 	    break;
206*86d7f5d3SJohn Marino 	}
207*86d7f5d3SJohn Marino       }
208*86d7f5d3SJohn Marino }
209*86d7f5d3SJohn Marino 
210*86d7f5d3SJohn Marino void
AliasHandlePptpIn(struct ip * pip,struct alias_link * link)211*86d7f5d3SJohn Marino AliasHandlePptpIn(struct ip *pip,	   /* IP packet to examine/patch */
212*86d7f5d3SJohn Marino                   struct alias_link *link) /* The PPTP control link */
213*86d7f5d3SJohn Marino {
214*86d7f5d3SJohn Marino     struct alias_link   *pptp_link;
215*86d7f5d3SJohn Marino     PptpCallId    	cptr;
216*86d7f5d3SJohn Marino     u_int16_t     	*pcall_id;
217*86d7f5d3SJohn Marino     u_int16_t           ctl_type;           /* control message type */
218*86d7f5d3SJohn Marino     struct tcphdr 	*tc;
219*86d7f5d3SJohn Marino 
220*86d7f5d3SJohn Marino     /* Verify valid PPTP control message */
221*86d7f5d3SJohn Marino     if ((cptr = AliasVerifyPptp(pip, &ctl_type)) == NULL)
222*86d7f5d3SJohn Marino       return;
223*86d7f5d3SJohn Marino 
224*86d7f5d3SJohn Marino     /* Modify certain PPTP messages */
225*86d7f5d3SJohn Marino     switch (ctl_type)
226*86d7f5d3SJohn Marino     {
227*86d7f5d3SJohn Marino     case PPTP_InCallConn:
228*86d7f5d3SJohn Marino     case PPTP_WanErrorNotify:
229*86d7f5d3SJohn Marino     case PPTP_SetLinkInfo:
230*86d7f5d3SJohn Marino       pcall_id = &cptr->cid1;
231*86d7f5d3SJohn Marino       break;
232*86d7f5d3SJohn Marino     case PPTP_OutCallReply:
233*86d7f5d3SJohn Marino     case PPTP_InCallReply:
234*86d7f5d3SJohn Marino       pcall_id = &cptr->cid2;
235*86d7f5d3SJohn Marino       break;
236*86d7f5d3SJohn Marino     case PPTP_CallDiscNotify:			/* Connection closed. */
237*86d7f5d3SJohn Marino       pptp_link = FindPptpInByCallId(GetDestAddress(link),
238*86d7f5d3SJohn Marino 				     GetAliasAddress(link),
239*86d7f5d3SJohn Marino 				     cptr->cid1);
240*86d7f5d3SJohn Marino       if (pptp_link != NULL)
241*86d7f5d3SJohn Marino 	    SetExpire(pptp_link, 0);
242*86d7f5d3SJohn Marino       return;
243*86d7f5d3SJohn Marino     default:
244*86d7f5d3SJohn Marino       return;
245*86d7f5d3SJohn Marino     }
246*86d7f5d3SJohn Marino 
247*86d7f5d3SJohn Marino     /* Find PPTP link for address and Call ID found in PPTP Control Msg */
248*86d7f5d3SJohn Marino     pptp_link = FindPptpInByPeerCallId(GetDestAddress(link),
249*86d7f5d3SJohn Marino 				       GetAliasAddress(link),
250*86d7f5d3SJohn Marino 				       *pcall_id);
251*86d7f5d3SJohn Marino 
252*86d7f5d3SJohn Marino     if (pptp_link != NULL) {
253*86d7f5d3SJohn Marino       int accumulate = *pcall_id;
254*86d7f5d3SJohn Marino 
255*86d7f5d3SJohn Marino       /* De-alias the Peer's Call Id. */
256*86d7f5d3SJohn Marino       *pcall_id = GetOriginalPort(pptp_link);
257*86d7f5d3SJohn Marino 
258*86d7f5d3SJohn Marino       /* Compute TCP checksum for modified packet */
259*86d7f5d3SJohn Marino       tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
260*86d7f5d3SJohn Marino       accumulate -= *pcall_id;
261*86d7f5d3SJohn Marino       ADJUST_CHECKSUM(accumulate, tc->th_sum);
262*86d7f5d3SJohn Marino 
263*86d7f5d3SJohn Marino       if (ctl_type == PPTP_OutCallReply || ctl_type == PPTP_InCallReply) {
264*86d7f5d3SJohn Marino 	    PptpCode codes = (PptpCode)(cptr + 1);
265*86d7f5d3SJohn Marino 
266*86d7f5d3SJohn Marino 	    if (codes->resCode == 1)		/* Connection established, */
267*86d7f5d3SJohn Marino 		SetDestCallId(pptp_link,	/* note the Call ID. */
268*86d7f5d3SJohn Marino 			      cptr->cid1);
269*86d7f5d3SJohn Marino 	    else
270*86d7f5d3SJohn Marino 		SetExpire(pptp_link, 0);	/* Connection refused. */
271*86d7f5d3SJohn Marino       }
272*86d7f5d3SJohn Marino     }
273*86d7f5d3SJohn Marino }
274*86d7f5d3SJohn Marino 
275*86d7f5d3SJohn Marino static PptpCallId
AliasVerifyPptp(struct ip * pip,u_int16_t * ptype)276*86d7f5d3SJohn Marino AliasVerifyPptp(struct ip *pip, u_int16_t *ptype) /* IP packet to examine/patch */
277*86d7f5d3SJohn Marino {
278*86d7f5d3SJohn Marino     int           	hlen, tlen, dlen;
279*86d7f5d3SJohn Marino     PptpMsgHead   	hptr;
280*86d7f5d3SJohn Marino     struct tcphdr 	*tc;
281*86d7f5d3SJohn Marino 
282*86d7f5d3SJohn Marino     /* Calculate some lengths */
283*86d7f5d3SJohn Marino     tc = (struct tcphdr *) ((char *) pip + (pip->ip_hl << 2));
284*86d7f5d3SJohn Marino     hlen = (pip->ip_hl + tc->th_off) << 2;
285*86d7f5d3SJohn Marino     tlen = ntohs(pip->ip_len);
286*86d7f5d3SJohn Marino     dlen = tlen - hlen;
287*86d7f5d3SJohn Marino 
288*86d7f5d3SJohn Marino     /* Verify data length */
289*86d7f5d3SJohn Marino     if (dlen < (sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds)))
290*86d7f5d3SJohn Marino       return(NULL);
291*86d7f5d3SJohn Marino 
292*86d7f5d3SJohn Marino     /* Move up to PPTP message header */
293*86d7f5d3SJohn Marino     hptr = (PptpMsgHead)(((char *) pip) + hlen);
294*86d7f5d3SJohn Marino 
295*86d7f5d3SJohn Marino     /* Return the control message type */
296*86d7f5d3SJohn Marino     *ptype = ntohs(hptr->type);
297*86d7f5d3SJohn Marino 
298*86d7f5d3SJohn Marino     /* Verify PPTP Control Message */
299*86d7f5d3SJohn Marino     if ((ntohs(hptr->msgType) != PPTP_CTRL_MSG_TYPE) ||
300*86d7f5d3SJohn Marino         (ntohl(hptr->magic) != PPTP_MAGIC))
301*86d7f5d3SJohn Marino       return(NULL);
302*86d7f5d3SJohn Marino 
303*86d7f5d3SJohn Marino     /* Verify data length. */
304*86d7f5d3SJohn Marino     if ((*ptype == PPTP_OutCallReply || *ptype == PPTP_InCallReply) &&
305*86d7f5d3SJohn Marino 	(dlen < sizeof(struct pptpMsgHead) + sizeof(struct pptpCallIds) +
306*86d7f5d3SJohn Marino 		sizeof(struct pptpCodes)))
307*86d7f5d3SJohn Marino 	return (NULL);
308*86d7f5d3SJohn Marino     else
309*86d7f5d3SJohn Marino 	return (PptpCallId)(hptr + 1);
310*86d7f5d3SJohn Marino }
311*86d7f5d3SJohn Marino 
312*86d7f5d3SJohn Marino 
313*86d7f5d3SJohn Marino int
AliasHandlePptpGreOut(struct ip * pip)314*86d7f5d3SJohn Marino AliasHandlePptpGreOut(struct ip *pip)
315*86d7f5d3SJohn Marino {
316*86d7f5d3SJohn Marino     GreHdr		*gr;
317*86d7f5d3SJohn Marino     struct alias_link	*link;
318*86d7f5d3SJohn Marino 
319*86d7f5d3SJohn Marino     gr = (GreHdr *)((char *)pip + (pip->ip_hl << 2));
320*86d7f5d3SJohn Marino 
321*86d7f5d3SJohn Marino     /* Check GRE header bits. */
322*86d7f5d3SJohn Marino     if ((ntohl(*((u_int32_t *)gr)) & PPTP_INIT_MASK) != PPTP_INIT_VALUE)
323*86d7f5d3SJohn Marino 	return (-1);
324*86d7f5d3SJohn Marino 
325*86d7f5d3SJohn Marino     link = FindPptpOutByPeerCallId(pip->ip_src, pip->ip_dst, gr->gh_call_id);
326*86d7f5d3SJohn Marino     if (link != NULL) {
327*86d7f5d3SJohn Marino 	struct in_addr alias_addr = GetAliasAddress(link);
328*86d7f5d3SJohn Marino 
329*86d7f5d3SJohn Marino 	/* Change source IP address. */
330*86d7f5d3SJohn Marino 	DifferentialChecksum(&pip->ip_sum,
331*86d7f5d3SJohn Marino 			     (u_short *)&alias_addr,
332*86d7f5d3SJohn Marino 			     (u_short *)&pip->ip_src,
333*86d7f5d3SJohn Marino 			     2);
334*86d7f5d3SJohn Marino 	pip->ip_src = alias_addr;
335*86d7f5d3SJohn Marino     }
336*86d7f5d3SJohn Marino 
337*86d7f5d3SJohn Marino     return (0);
338*86d7f5d3SJohn Marino }
339*86d7f5d3SJohn Marino 
340*86d7f5d3SJohn Marino 
341*86d7f5d3SJohn Marino int
AliasHandlePptpGreIn(struct ip * pip)342*86d7f5d3SJohn Marino AliasHandlePptpGreIn(struct ip *pip)
343*86d7f5d3SJohn Marino {
344*86d7f5d3SJohn Marino     GreHdr		*gr;
345*86d7f5d3SJohn Marino     struct alias_link	*link;
346*86d7f5d3SJohn Marino 
347*86d7f5d3SJohn Marino     gr = (GreHdr *)((char *)pip + (pip->ip_hl << 2));
348*86d7f5d3SJohn Marino 
349*86d7f5d3SJohn Marino     /* Check GRE header bits. */
350*86d7f5d3SJohn Marino     if ((ntohl(*((u_int32_t *)gr)) & PPTP_INIT_MASK) != PPTP_INIT_VALUE)
351*86d7f5d3SJohn Marino 	return (-1);
352*86d7f5d3SJohn Marino 
353*86d7f5d3SJohn Marino     link = FindPptpInByPeerCallId(pip->ip_src, pip->ip_dst, gr->gh_call_id);
354*86d7f5d3SJohn Marino     if (link != NULL) {
355*86d7f5d3SJohn Marino 	struct in_addr src_addr = GetOriginalAddress(link);
356*86d7f5d3SJohn Marino 
357*86d7f5d3SJohn Marino 	/* De-alias the Peer's Call Id. */
358*86d7f5d3SJohn Marino 	gr->gh_call_id = GetOriginalPort(link);
359*86d7f5d3SJohn Marino 
360*86d7f5d3SJohn Marino 	/* Restore original IP address. */
361*86d7f5d3SJohn Marino 	DifferentialChecksum(&pip->ip_sum,
362*86d7f5d3SJohn Marino 			     (u_short *)&src_addr,
363*86d7f5d3SJohn Marino 			     (u_short *)&pip->ip_dst,
364*86d7f5d3SJohn Marino 			     2);
365*86d7f5d3SJohn Marino 	pip->ip_dst = src_addr;
366*86d7f5d3SJohn Marino     }
367*86d7f5d3SJohn Marino 
368*86d7f5d3SJohn Marino     return (0);
369*86d7f5d3SJohn Marino }
370