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