1ab25eeb5Syz /*
2ab25eeb5Syz  * Copyright (C) 2002-2003 by Darren Reed
3ab25eeb5Syz  *
4ab25eeb5Syz  * Simple PPTP transparent proxy for in-kernel use.  For use with the NAT
5ab25eeb5Syz  * code.
6ab25eeb5Syz  *
7ab25eeb5Syz  * $Id: ip_pptp_pxy.c,v 2.10.2.10 2005/07/15 21:56:52 darrenr Exp $
8ab25eeb5Syz  *
9*33f2fefdSDarren Reed  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
10ab25eeb5Syz  * Use is subject to license terms.
11ab25eeb5Syz  */
12ab25eeb5Syz 
13ab25eeb5Syz #define	IPF_PPTP_PROXY
14ab25eeb5Syz 
15f4b3ec61Sdh typedef struct ifs_pptppxy {
16f4b3ec61Sdh 	frentry_t	pptpfr;
17f4b3ec61Sdh 	int		pptp_proxy_init;
18f4b3ec61Sdh } ifs_pptppxy_t;
19f4b3ec61Sdh 
20ab25eeb5Syz typedef	struct pptp_hdr {
21ab25eeb5Syz 	u_short	pptph_len;
22ab25eeb5Syz 	u_short	pptph_type;
23ab25eeb5Syz 	u_32_t	pptph_cookie;
24ab25eeb5Syz } pptp_hdr_t;
25ab25eeb5Syz 
26ab25eeb5Syz #define	PPTP_MSGTYPE_CTL	1
27ab25eeb5Syz #define	PPTP_MTCTL_STARTREQ	1
28ab25eeb5Syz #define	PPTP_MTCTL_STARTREP	2
29ab25eeb5Syz #define	PPTP_MTCTL_STOPREQ	3
30ab25eeb5Syz #define	PPTP_MTCTL_STOPREP	4
31ab25eeb5Syz #define	PPTP_MTCTL_ECHOREQ	5
32ab25eeb5Syz #define	PPTP_MTCTL_ECHOREP	6
33ab25eeb5Syz #define	PPTP_MTCTL_OUTREQ	7
34ab25eeb5Syz #define	PPTP_MTCTL_OUTREP	8
35ab25eeb5Syz #define	PPTP_MTCTL_INREQ	9
36ab25eeb5Syz #define	PPTP_MTCTL_INREP	10
37ab25eeb5Syz #define	PPTP_MTCTL_INCONNECT	11
38ab25eeb5Syz #define	PPTP_MTCTL_CLEAR	12
39ab25eeb5Syz #define	PPTP_MTCTL_DISCONNECT	13
40ab25eeb5Syz #define	PPTP_MTCTL_WANERROR	14
41ab25eeb5Syz #define	PPTP_MTCTL_LINKINFO	15
42ab25eeb5Syz 
43ab25eeb5Syz 
44f4b3ec61Sdh int ippr_pptp_init __P((void **, ipf_stack_t *));
45f4b3ec61Sdh void ippr_pptp_fini __P((void **, ipf_stack_t *));
46f4b3ec61Sdh int ippr_pptp_new __P((fr_info_t *, ap_session_t *, nat_t *, void *));
47f4b3ec61Sdh void ippr_pptp_del __P((ap_session_t *, void *, ipf_stack_t *));
48f4b3ec61Sdh int ippr_pptp_inout __P((fr_info_t *, ap_session_t *, nat_t *, void *));
49f4b3ec61Sdh void ippr_pptp_donatstate __P((fr_info_t *, nat_t *, pptp_pxy_t *, ifs_pptppxy_t *));
50f4b3ec61Sdh int ippr_pptp_message __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *, ifs_pptppxy_t *));
51f4b3ec61Sdh int ippr_pptp_nextmessage __P((fr_info_t *, nat_t *, pptp_pxy_t *, int, ifs_pptppxy_t *));
52f4b3ec61Sdh int ippr_pptp_mctl __P((fr_info_t *, nat_t *, pptp_pxy_t *, pptp_side_t *, ifs_pptppxy_t *));
53ab25eeb5Syz 
54f4b3ec61Sdh int	ippr_pptp_debug = 0;			/* It never changes */
55f4b3ec61Sdh int	ippr_pptp_gretimeout = IPF_TTLVAL(120);	/* 2 minutes, never changes */
56ab25eeb5Syz 
57ab25eeb5Syz /*
58ab25eeb5Syz  * PPTP application proxy initialization.
59ab25eeb5Syz  */
60f4b3ec61Sdh /*ARGSUSED*/
ippr_pptp_init(private,ifs)61f4b3ec61Sdh int ippr_pptp_init(private, ifs)
62f4b3ec61Sdh void **private;
63f4b3ec61Sdh ipf_stack_t *ifs;
64ab25eeb5Syz {
65f4b3ec61Sdh 	ifs_pptppxy_t *ifspptp;
66f4b3ec61Sdh 
67f4b3ec61Sdh 	KMALLOC(ifspptp, ifs_pptppxy_t *);
68f4b3ec61Sdh 	if (ifspptp == NULL)
69f4b3ec61Sdh 		return -1;
70f4b3ec61Sdh 
71f4b3ec61Sdh 	bzero((char *)&ifspptp->pptpfr, sizeof(ifspptp->pptpfr));
72f4b3ec61Sdh 	ifspptp->pptpfr.fr_ref = 1;
73f4b3ec61Sdh 	ifspptp->pptpfr.fr_age[0] = ippr_pptp_gretimeout;
74f4b3ec61Sdh 	ifspptp->pptpfr.fr_age[1] = ippr_pptp_gretimeout;
75f4b3ec61Sdh 	ifspptp->pptpfr.fr_flags = FR_OUTQUE|FR_PASS|FR_QUICK|FR_KEEPSTATE;
76f4b3ec61Sdh 	MUTEX_INIT(&ifspptp->pptpfr.fr_lock, "PPTP proxy rule lock");
77f4b3ec61Sdh 	ifspptp->pptp_proxy_init = 1;
78f4b3ec61Sdh 
79f4b3ec61Sdh 	*private = (void *)ifspptp;
80ab25eeb5Syz 
81ab25eeb5Syz 	return 0;
82ab25eeb5Syz }
83ab25eeb5Syz 
84ab25eeb5Syz 
85f4b3ec61Sdh /*ARGSUSED*/
ippr_pptp_fini(private,ifs)86f4b3ec61Sdh void ippr_pptp_fini(private, ifs)
87f4b3ec61Sdh void **private;
88f4b3ec61Sdh ipf_stack_t *ifs;
89ab25eeb5Syz {
90f4b3ec61Sdh 	ifs_pptppxy_t *ifspptp = *((ifs_pptppxy_t **)private);
91f4b3ec61Sdh 
92f4b3ec61Sdh 	if (ifspptp->pptp_proxy_init == 1) {
93f4b3ec61Sdh 		MUTEX_DESTROY(&ifspptp->pptpfr.fr_lock);
94f4b3ec61Sdh 		ifspptp->pptp_proxy_init = 0;
95ab25eeb5Syz 	}
96f4b3ec61Sdh 
97f4b3ec61Sdh 	KFREE(ifspptp);
98f4b3ec61Sdh 	*private = NULL;
99ab25eeb5Syz }
100ab25eeb5Syz 
101ab25eeb5Syz 
102ab25eeb5Syz /*
103ab25eeb5Syz  * Setup for a new PPTP proxy.
104ab25eeb5Syz  */
105f4b3ec61Sdh /*ARGSUSED*/
ippr_pptp_new(fin,aps,nat,private)106f4b3ec61Sdh int ippr_pptp_new(fin, aps, nat, private)
107ab25eeb5Syz fr_info_t *fin;
108ab25eeb5Syz ap_session_t *aps;
109ab25eeb5Syz nat_t *nat;
110f4b3ec61Sdh void *private;
111ab25eeb5Syz {
112ab25eeb5Syz 	pptp_pxy_t *pptp;
113ab25eeb5Syz 	ipnat_t *ipn;
114ab25eeb5Syz 	ip_t *ip;
115ab25eeb5Syz 
116ab25eeb5Syz 	ip = fin->fin_ip;
117ab25eeb5Syz 
118ab25eeb5Syz 	if (nat_outlookup(fin, 0, IPPROTO_GRE, nat->nat_inip,
119ab25eeb5Syz 			  ip->ip_dst) != NULL) {
120ab25eeb5Syz 		if (ippr_pptp_debug > 0)
121ab25eeb5Syz 			printf("ippr_pptp_new: GRE session already exists\n");
122ab25eeb5Syz 		return -1;
123ab25eeb5Syz 	}
124ab25eeb5Syz 
125ab25eeb5Syz 	aps->aps_psiz = sizeof(*pptp);
126ab25eeb5Syz 	KMALLOCS(aps->aps_data, pptp_pxy_t *, sizeof(*pptp));
127ab25eeb5Syz 	if (aps->aps_data == NULL) {
128ab25eeb5Syz 		if (ippr_pptp_debug > 0)
129ab25eeb5Syz 			printf("ippr_pptp_new: malloc for aps_data failed\n");
130ab25eeb5Syz 		return -1;
131ab25eeb5Syz 	}
132ab25eeb5Syz 
133ab25eeb5Syz 	/*
134ab25eeb5Syz 	 * Create NAT rule against which the tunnel/transport mapping is
135ab25eeb5Syz 	 * created.  This is required because the current NAT rule does not
136ab25eeb5Syz 	 * describe GRE but TCP instead.
137