Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f09943fe authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: nf_conntrack/nf_nat: add PPTP helper port



Add nf_conntrack port of the PPtP conntrack/NAT helper. Since there seems
to be no IPv6-capable PPtP implementation the helper only support IPv4.

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 92703eee
Loading
Loading
Loading
Loading
+321 −0
Original line number Diff line number Diff line
/* PPTP constants and structs */
#ifndef _NF_CONNTRACK_PPTP_H
#define _NF_CONNTRACK_PPTP_H

/* state of the control session */
enum pptp_ctrlsess_state {
	PPTP_SESSION_NONE,			/* no session present */
	PPTP_SESSION_ERROR,			/* some session error */
	PPTP_SESSION_STOPREQ,			/* stop_sess request seen */
	PPTP_SESSION_REQUESTED,			/* start_sess request seen */
	PPTP_SESSION_CONFIRMED,			/* session established */
};

/* state of the call inside the control session */
enum pptp_ctrlcall_state {
	PPTP_CALL_NONE,
	PPTP_CALL_ERROR,
	PPTP_CALL_OUT_REQ,
	PPTP_CALL_OUT_CONF,
	PPTP_CALL_IN_REQ,
	PPTP_CALL_IN_REP,
	PPTP_CALL_IN_CONF,
	PPTP_CALL_CLEAR_REQ,
};

/* conntrack private data */
struct nf_ct_pptp_master {
	enum pptp_ctrlsess_state sstate;	/* session state */
	enum pptp_ctrlcall_state cstate;	/* call state */
	__be16 pac_call_id;			/* call id of PAC */
	__be16 pns_call_id;			/* call id of PNS */

	/* in pre-2.6.11 this used to be per-expect. Now it is per-conntrack
	 * and therefore imposes a fixed limit on the number of maps */
	struct nf_ct_gre_keymap *keymap[IP_CT_DIR_MAX];
};

struct nf_nat_pptp {
	__be16 pns_call_id;			/* NAT'ed PNS call id */
	__be16 pac_call_id;			/* NAT'ed PAC call id */
};

#ifdef __KERNEL__

#define PPTP_CONTROL_PORT	1723

#define PPTP_PACKET_CONTROL	1
#define PPTP_PACKET_MGMT	2

#define PPTP_MAGIC_COOKIE	0x1a2b3c4d

struct pptp_pkt_hdr {
	__u16	packetLength;
	__be16	packetType;
	__be32	magicCookie;
};

/* PptpControlMessageType values */
#define PPTP_START_SESSION_REQUEST	1
#define PPTP_START_SESSION_REPLY	2
#define PPTP_STOP_SESSION_REQUEST	3
#define PPTP_STOP_SESSION_REPLY		4
#define PPTP_ECHO_REQUEST		5
#define PPTP_ECHO_REPLY			6
#define PPTP_OUT_CALL_REQUEST		7
#define PPTP_OUT_CALL_REPLY		8
#define PPTP_IN_CALL_REQUEST		9
#define PPTP_IN_CALL_REPLY		10
#define PPTP_IN_CALL_CONNECT		11
#define PPTP_CALL_CLEAR_REQUEST		12
#define PPTP_CALL_DISCONNECT_NOTIFY	13
#define PPTP_WAN_ERROR_NOTIFY		14
#define PPTP_SET_LINK_INFO		15

#define PPTP_MSG_MAX			15

/* PptpGeneralError values */
#define PPTP_ERROR_CODE_NONE		0
#define PPTP_NOT_CONNECTED		1
#define PPTP_BAD_FORMAT			2
#define PPTP_BAD_VALUE			3
#define PPTP_NO_RESOURCE		4
#define PPTP_BAD_CALLID			5
#define PPTP_REMOVE_DEVICE_ERROR	6

struct PptpControlHeader {
	__be16	messageType;
	__u16	reserved;
};

/* FramingCapability Bitmap Values */
#define PPTP_FRAME_CAP_ASYNC		0x1
#define PPTP_FRAME_CAP_SYNC		0x2

/* BearerCapability Bitmap Values */
#define PPTP_BEARER_CAP_ANALOG		0x1
#define PPTP_BEARER_CAP_DIGITAL		0x2

struct PptpStartSessionRequest {
	__be16	protocolVersion;
	__u16	reserved1;
	__be32	framingCapability;
	__be32	bearerCapability;
	__be16	maxChannels;
	__be16	firmwareRevision;
	__u8	hostName[64];
	__u8	vendorString[64];
};

/* PptpStartSessionResultCode Values */
#define PPTP_START_OK			1
#define PPTP_START_GENERAL_ERROR	2
#define PPTP_START_ALREADY_CONNECTED	3
#define PPTP_START_NOT_AUTHORIZED	4
#define PPTP_START_UNKNOWN_PROTOCOL	5

struct PptpStartSessionReply {
	__be16	protocolVersion;
	__u8	resultCode;
	__u8	generalErrorCode;
	__be32	framingCapability;
	__be32	bearerCapability;
	__be16	maxChannels;
	__be16	firmwareRevision;
	__u8	hostName[64];
	__u8	vendorString[64];
};

/* PptpStopReasons */
#define PPTP_STOP_NONE			1
#define PPTP_STOP_PROTOCOL		2
#define PPTP_STOP_LOCAL_SHUTDOWN	3

struct PptpStopSessionRequest {
	__u8	reason;
	__u8	reserved1;
	__u16	reserved2;
};

/* PptpStopSessionResultCode */
#define PPTP_STOP_OK			1
#define PPTP_STOP_GENERAL_ERROR		2

struct PptpStopSessionReply {
	__u8	resultCode;
	__u8	generalErrorCode;
	__u16	reserved1;
};

struct PptpEchoRequest {
	__be32 identNumber;
};

/* PptpEchoReplyResultCode */
#define PPTP_ECHO_OK			1
#define PPTP_ECHO_GENERAL_ERROR		2

struct PptpEchoReply {
	__be32	identNumber;
	__u8	resultCode;
	__u8	generalErrorCode;
	__u16	reserved;
};

/* PptpFramingType */
#define PPTP_ASYNC_FRAMING		1
#define PPTP_SYNC_FRAMING		2
#define PPTP_DONT_CARE_FRAMING		3

/* PptpCallBearerType */
#define PPTP_ANALOG_TYPE		1
#define PPTP_DIGITAL_TYPE		2
#define PPTP_DONT_CARE_BEARER_TYPE	3

struct PptpOutCallRequest {
	__be16	callID;
	__be16	callSerialNumber;
	__be32	minBPS;
	__be32	maxBPS;
	__be32	bearerType;
	__be32	framingType;
	__be16	packetWindow;
	__be16	packetProcDelay;
	__be16	phoneNumberLength;
	__u16	reserved1;
	__u8	phoneNumber[64];
	__u8	subAddress[64];
};

/* PptpCallResultCode */
#define PPTP_OUTCALL_CONNECT		1
#define PPTP_OUTCALL_GENERAL_ERROR	2
#define PPTP_OUTCALL_NO_CARRIER		3
#define PPTP_OUTCALL_BUSY		4
#define PPTP_OUTCALL_NO_DIAL_TONE	5
#define PPTP_OUTCALL_TIMEOUT		6
#define PPTP_OUTCALL_DONT_ACCEPT	7

struct PptpOutCallReply {
	__be16	callID;
	__be16	peersCallID;
	__u8	resultCode;
	__u8	generalErrorCode;
	__be16	causeCode;
	__be32	connectSpeed;
	__be16	packetWindow;
	__be16	packetProcDelay;
	__be32	physChannelID;
};

struct PptpInCallRequest {
	__be16	callID;
	__be16	callSerialNumber;
	__be32	callBearerType;
	__be32	physChannelID;
	__be16	dialedNumberLength;
	__be16	dialingNumberLength;
	__u8	dialedNumber[64];
	__u8	dialingNumber[64];
	__u8	subAddress[64];
};

/* PptpInCallResultCode */
#define PPTP_INCALL_ACCEPT		1
#define PPTP_INCALL_GENERAL_ERROR	2
#define PPTP_INCALL_DONT_ACCEPT		3

struct PptpInCallReply {
	__be16	callID;
	__be16	peersCallID;
	__u8	resultCode;
	__u8	generalErrorCode;
	__be16	packetWindow;
	__be16	packetProcDelay;
	__u16	reserved;
};

struct PptpInCallConnected {
	__be16	peersCallID;
	__u16	reserved;
	__be32	connectSpeed;
	__be16	packetWindow;
	__be16	packetProcDelay;
	__be32	callFramingType;
};

struct PptpClearCallRequest {
	__be16	callID;
	__u16	reserved;
};

struct PptpCallDisconnectNotify {
	__be16	callID;
	__u8	resultCode;
	__u8	generalErrorCode;
	__be16	causeCode;
	__u16	reserved;
	__u8	callStatistics[128];
};

struct PptpWanErrorNotify {
	__be16	peersCallID;
	__u16	reserved;
	__be32	crcErrors;
	__be32	framingErrors;
	__be32	hardwareOverRuns;
	__be32	bufferOverRuns;
	__be32	timeoutErrors;
	__be32	alignmentErrors;
};

struct PptpSetLinkInfo {
	__be16	peersCallID;
	__u16	reserved;
	__be32	sendAccm;
	__be32	recvAccm;
};

union pptp_ctrl_union {
	struct PptpStartSessionRequest	sreq;
	struct PptpStartSessionReply	srep;
	struct PptpStopSessionRequest	streq;
	struct PptpStopSessionReply	strep;
	struct PptpOutCallRequest	ocreq;
	struct PptpOutCallReply		ocack;
	struct PptpInCallRequest	icreq;
	struct PptpInCallReply		icack;
	struct PptpInCallConnected	iccon;
	struct PptpClearCallRequest	clrreq;
	struct PptpCallDisconnectNotify disc;
	struct PptpWanErrorNotify	wanerr;
	struct PptpSetLinkInfo		setlink;
};

/* crap needed for nf_conntrack_compat.h */
struct nf_conn;
struct nf_conntrack_expect;
enum ip_conntrack_info;

extern int
(*nf_nat_pptp_hook_outbound)(struct sk_buff **pskb,
			     struct nf_conn *ct, enum ip_conntrack_info ctinfo,
			     struct PptpControlHeader *ctlh,
			     union pptp_ctrl_union *pptpReq);

extern int
(*nf_nat_pptp_hook_inbound)(struct sk_buff **pskb,
			    struct nf_conn *ct, enum ip_conntrack_info ctinfo,
			    struct PptpControlHeader *ctlh,
			    union pptp_ctrl_union *pptpReq);

extern void
(*nf_nat_pptp_hook_exp_gre)(struct nf_conntrack_expect *exp_orig,
			    struct nf_conntrack_expect *exp_reply);

extern void
(*nf_nat_pptp_hook_expectfn)(struct nf_conn *ct,
			     struct nf_conntrack_expect *exp);

#endif /* __KERNEL__ */
#endif /* _NF_CONNTRACK_PPTP_H */
+112 −0
Original line number Diff line number Diff line
#ifndef _CONNTRACK_PROTO_GRE_H
#define _CONNTRACK_PROTO_GRE_H
#include <asm/byteorder.h>

/* GRE PROTOCOL HEADER */

/* GRE Version field */
#define GRE_VERSION_1701	0x0
#define GRE_VERSION_PPTP	0x1

/* GRE Protocol field */
#define GRE_PROTOCOL_PPTP	0x880B

/* GRE Flags */
#define GRE_FLAG_C		0x80
#define GRE_FLAG_R		0x40
#define GRE_FLAG_K		0x20
#define GRE_FLAG_S		0x10
#define GRE_FLAG_A		0x80

#define GRE_IS_C(f)	((f)&GRE_FLAG_C)
#define GRE_IS_R(f)	((f)&GRE_FLAG_R)
#define GRE_IS_K(f)	((f)&GRE_FLAG_K)
#define GRE_IS_S(f)	((f)&GRE_FLAG_S)
#define GRE_IS_A(f)	((f)&GRE_FLAG_A)

/* GRE is a mess: Four different standards */
struct gre_hdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
	__u16	rec:3,
		srr:1,
		seq:1,
		key:1,
		routing:1,
		csum:1,
		version:3,
		reserved:4,
		ack:1;
#elif defined(__BIG_ENDIAN_BITFIELD)
	__u16	csum:1,
		routing:1,
		key:1,
		seq:1,
		srr:1,
		rec:3,
		ack:1,
		reserved:4,
		version:3;
#else
#error "Adjust your <asm/byteorder.h> defines"
#endif
	__be16	protocol;
};

/* modified GRE header for PPTP */
struct gre_hdr_pptp {
	__u8   flags;		/* bitfield */
	__u8   version;		/* should be GRE_VERSION_PPTP */
	__be16 protocol;	/* should be GRE_PROTOCOL_PPTP */
	__be16 payload_len;	/* size of ppp payload, not inc. gre header */
	__be16 call_id;		/* peer's call_id for this session */
	__be32 seq;		/* sequence number.  Present if S==1 */
	__be32 ack;		/* seq number of highest packet recieved by */
				/*  sender in this session */
};

struct nf_ct_gre {
	unsigned int stream_timeout;
	unsigned int timeout;
};

#ifdef __KERNEL__
#include <net/netfilter/nf_conntrack_tuple.h>

struct nf_conn;

/* structure for original <-> reply keymap */
struct nf_ct_gre_keymap {
	struct list_head list;
	struct nf_conntrack_tuple tuple;
};

/* add new tuple->key_reply pair to keymap */
int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
			 struct nf_conntrack_tuple *t);

/* delete keymap entries */
void nf_ct_gre_keymap_destroy(struct nf_conn *ct);

/* get pointer to gre key, if present */
static inline __be32 *gre_key(struct gre_hdr *greh)
{
	if (!greh->key)
		return NULL;
	if (greh->csum || greh->routing)
		return (__be32 *)(greh+sizeof(*greh)+4);
	return (__be32 *)(greh+sizeof(*greh));
}

/* get pointer ot gre csum, if present */
static inline __sum16 *gre_csum(struct gre_hdr *greh)
{
	if (!greh->csum)
		return NULL;
	return (__sum16 *)(greh+sizeof(*greh));
}

extern void nf_ct_gre_keymap_flush(void);
extern void nf_nat_need_gre(void);

#endif /* __KERNEL__ */
#endif /* _CONNTRACK_PROTO_GRE_H */
+2 −0
Original line number Diff line number Diff line
@@ -11,10 +11,12 @@

#ifdef CONFIG_NF_NAT_NEEDED
#include <net/netfilter/nf_nat.h>
#include <linux/netfilter/nf_conntrack_pptp.h>

/* per conntrack: nat application helper private data */
union nf_conntrack_nat_help {
        /* insert nat helper private data here */
	struct nf_nat_pptp nat_pptp_info;
};

struct nf_conn_nat {
+4 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@

#include <linux/netfilter/nf_conntrack_tcp.h>
#include <linux/netfilter/nf_conntrack_sctp.h>
#include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <net/netfilter/ipv4/nf_conntrack_icmp.h>
#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>

@@ -33,6 +34,7 @@ union nf_conntrack_proto {
	struct ip_ct_tcp tcp;
	struct ip_ct_icmp icmp;
	struct nf_ct_icmpv6 icmpv6;
	struct nf_ct_gre gre;
};

union nf_conntrack_expect_proto {
@@ -41,12 +43,14 @@ union nf_conntrack_expect_proto {

/* Add protocol helper include file here */
#include <linux/netfilter/nf_conntrack_ftp.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
#include <linux/netfilter/nf_conntrack_h323.h>

/* per conntrack: application helper private data */
union nf_conntrack_help {
	/* insert conntrack helper private data (master) here */
	struct nf_ct_ftp_master ct_ftp_info;
	struct nf_ct_pptp_master ct_pptp_info;
	struct nf_ct_h323_master ct_h323_info;
};

+2 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ struct nf_conntrack_helper
		    struct nf_conn *ct,
		    enum ip_conntrack_info conntrackinfo);

	void (*destroy)(struct nf_conn *ct);

	int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
};

Loading