Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
875bd5ab
Commit
875bd5ab
authored
Sep 19, 2005
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
parents
6d1cfe3f
e14c3caf
Changes
28
Hide whitespace changes
Inline
Side-by-side
Showing
28 changed files
with
2382 additions
and
496 deletions
+2382
-496
drivers/net/wan/hdlc_cisco.c
drivers/net/wan/hdlc_cisco.c
+1
-1
include/linux/if_vlan.h
include/linux/if_vlan.h
+4
-4
include/linux/netfilter_ipv4/ip_conntrack.h
include/linux/netfilter_ipv4/ip_conntrack.h
+13
-1
include/linux/netfilter_ipv4/ip_conntrack_pptp.h
include/linux/netfilter_ipv4/ip_conntrack_pptp.h
+332
-0
include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
+114
-0
include/linux/netfilter_ipv4/ip_conntrack_tuple.h
include/linux/netfilter_ipv4/ip_conntrack_tuple.h
+7
-0
include/linux/netfilter_ipv4/ip_nat_pptp.h
include/linux/netfilter_ipv4/ip_nat_pptp.h
+11
-0
include/linux/netfilter_ipv6/ip6_tables.h
include/linux/netfilter_ipv6/ip6_tables.h
+3
-0
net/8021q/vlan_dev.c
net/8021q/vlan_dev.c
+1
-1
net/ipv4/fib_trie.c
net/ipv4/fib_trie.c
+17
-17
net/ipv4/netfilter/Kconfig
net/ipv4/netfilter/Kconfig
+22
-0
net/ipv4/netfilter/Makefile
net/ipv4/netfilter/Makefile
+5
-0
net/ipv4/netfilter/ip_conntrack_core.c
net/ipv4/netfilter/ip_conntrack_core.c
+1
-1
net/ipv4/netfilter/ip_conntrack_helper_pptp.c
net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+805
-0
net/ipv4/netfilter/ip_conntrack_netlink.c
net/ipv4/netfilter/ip_conntrack_netlink.c
+2
-2
net/ipv4/netfilter/ip_conntrack_proto_gre.c
net/ipv4/netfilter/ip_conntrack_proto_gre.c
+327
-0
net/ipv4/netfilter/ip_conntrack_standalone.c
net/ipv4/netfilter/ip_conntrack_standalone.c
+2
-2
net/ipv4/netfilter/ip_nat_core.c
net/ipv4/netfilter/ip_nat_core.c
+2
-0
net/ipv4/netfilter/ip_nat_helper_pptp.c
net/ipv4/netfilter/ip_nat_helper_pptp.c
+401
-0
net/ipv4/netfilter/ip_nat_proto_gre.c
net/ipv4/netfilter/ip_nat_proto_gre.c
+214
-0
net/ipv4/tcp_output.c
net/ipv4/tcp_output.c
+7
-3
net/ipv6/netfilter/ip6_tables.c
net/ipv6/netfilter/ip6_tables.c
+52
-0
net/ipv6/netfilter/ip6t_ah.c
net/ipv6/netfilter/ip6t_ah.c
+5
-76
net/ipv6/netfilter/ip6t_dst.c
net/ipv6/netfilter/ip6t_dst.c
+7
-81
net/ipv6/netfilter/ip6t_esp.c
net/ipv6/netfilter/ip6t_esp.c
+4
-69
net/ipv6/netfilter/ip6t_frag.c
net/ipv6/netfilter/ip6t_frag.c
+9
-81
net/ipv6/netfilter/ip6t_hbh.c
net/ipv6/netfilter/ip6t_hbh.c
+7
-81
net/ipv6/netfilter/ip6t_rt.c
net/ipv6/netfilter/ip6t_rt.c
+7
-76
No files found.
drivers/net/wan/hdlc_cisco.c
View file @
875bd5ab
...
...
@@ -72,7 +72,7 @@ static void cisco_keepalive_send(struct net_device *dev, u32 type,
}
skb_reserve
(
skb
,
4
);
cisco_hard_header
(
skb
,
dev
,
CISCO_KEEPALIVE
,
NULL
,
NULL
,
0
);
data
=
(
cisco_packet
*
)
skb
->
data
;
data
=
(
cisco_packet
*
)
(
skb
->
data
+
4
)
;
data
->
type
=
htonl
(
type
);
data
->
par1
=
htonl
(
par1
);
...
...
include/linux/if_vlan.h
View file @
875bd5ab
...
...
@@ -42,8 +42,8 @@ struct hlist_node;
struct
vlan_ethhdr
{
unsigned
char
h_dest
[
ETH_ALEN
];
/* destination eth addr */
unsigned
char
h_source
[
ETH_ALEN
];
/* source ether addr */
unsigned
short
h_vlan_proto
;
/* Should always be 0x8100 */
unsigned
short
h_vlan_TCI
;
/* Encapsulates priority and VLAN ID */
__be16
h_vlan_proto
;
/* Should always be 0x8100 */
__be16
h_vlan_TCI
;
/* Encapsulates priority and VLAN ID */
unsigned
short
h_vlan_encapsulated_proto
;
/* packet type ID field (or len) */
};
...
...
@@ -55,8 +55,8 @@ static inline struct vlan_ethhdr *vlan_eth_hdr(const struct sk_buff *skb)
}
struct
vlan_hdr
{
unsigned
short
h_vlan_TCI
;
/* Encapsulates priority and VLAN ID */
unsigned
short
h_vlan_encapsulated_proto
;
/* packet type ID field (or len) */
__be16
h_vlan_TCI
;
/* Encapsulates priority and VLAN ID */
__be16
h_vlan_encapsulated_proto
;
/* packet type ID field (or len) */
};
#define VLAN_VID_MASK 0xfff
...
...
include/linux/netfilter_ipv4/ip_conntrack.h
View file @
875bd5ab
...
...
@@ -133,11 +133,13 @@ enum ip_conntrack_expect_events {
#include <linux/netfilter_ipv4/ip_conntrack_tcp.h>
#include <linux/netfilter_ipv4/ip_conntrack_icmp.h>
#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
#include <linux/netfilter_ipv4/ip_conntrack_sctp.h>
/* per conntrack: protocol private data */
union
ip_conntrack_proto
{
/* insert conntrack proto private data here */
struct
ip_ct_gre
gre
;
struct
ip_ct_sctp
sctp
;
struct
ip_ct_tcp
tcp
;
struct
ip_ct_icmp
icmp
;
...
...
@@ -148,6 +150,7 @@ union ip_conntrack_expect_proto {
};
/* Add protocol helper include file here */
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
#include <linux/netfilter_ipv4/ip_conntrack_amanda.h>
#include <linux/netfilter_ipv4/ip_conntrack_ftp.h>
#include <linux/netfilter_ipv4/ip_conntrack_irc.h>
...
...
@@ -155,12 +158,20 @@ union ip_conntrack_expect_proto {
/* per conntrack: application helper private data */
union
ip_conntrack_help
{
/* insert conntrack helper private data (master) here */
struct
ip_ct_pptp_master
ct_pptp_info
;
struct
ip_ct_ftp_master
ct_ftp_info
;
struct
ip_ct_irc_master
ct_irc_info
;
};
#ifdef CONFIG_IP_NF_NAT_NEEDED
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_pptp.h>
/* per conntrack: nat application helper private data */
union
ip_conntrack_nat_help
{
/* insert nat helper private data here */
struct
ip_nat_pptp
nat_pptp_info
;
};
#endif
#include <linux/types.h>
...
...
@@ -223,6 +234,7 @@ struct ip_conntrack
#ifdef CONFIG_IP_NF_NAT_NEEDED
struct
{
struct
ip_nat_info
info
;
union
ip_conntrack_nat_help
help
;
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
int
masq_index
;
...
...
@@ -372,7 +384,7 @@ extern struct ip_conntrack_expect *
__ip_conntrack_expect_find
(
const
struct
ip_conntrack_tuple
*
tuple
);
extern
struct
ip_conntrack_expect
*
ip_conntrack_expect_find
_get
(
const
struct
ip_conntrack_tuple
*
tuple
);
ip_conntrack_expect_find
(
const
struct
ip_conntrack_tuple
*
tuple
);
extern
struct
ip_conntrack_tuple_hash
*
__ip_conntrack_find
(
const
struct
ip_conntrack_tuple
*
tuple
,
...
...
include/linux/netfilter_ipv4/ip_conntrack_pptp.h
0 → 100644
View file @
875bd5ab
/* PPTP constants and structs */
#ifndef _CONNTRACK_PPTP_H
#define _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
ip_ct_pptp_master
{
enum
pptp_ctrlsess_state
sstate
;
/* session state */
/* everything below is going to be per-expectation in newnat,
* since there could be more than one call within one session */
enum
pptp_ctrlcall_state
cstate
;
/* call state */
u_int16_t
pac_call_id
;
/* call id of PAC, host byte order */
u_int16_t
pns_call_id
;
/* call id of PNS, host byte order */
/* 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
ip_ct_gre_keymap
*
keymap_orig
,
*
keymap_reply
;
};
/* conntrack_expect private member */
struct
ip_ct_pptp_expect
{
enum
pptp_ctrlcall_state
cstate
;
/* call state */
u_int16_t
pac_call_id
;
/* call id of PAC */
u_int16_t
pns_call_id
;
/* call id of PNS */
};
#ifdef __KERNEL__
#define IP_CONNTR_PPTP PPTP_CONTROL_PORT
#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
;
__u16
packetType
;
__u32
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
{
__u16
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
{
__u16
protocolVersion
;
__u8
reserved1
;
__u8
reserved2
;
__u32
framingCapability
;
__u32
bearerCapability
;
__u16
maxChannels
;
__u16
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
{
__u16
protocolVersion
;
__u8
resultCode
;
__u8
generalErrorCode
;
__u32
framingCapability
;
__u32
bearerCapability
;
__u16
maxChannels
;
__u16
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
;
};
/* PptpStopSessionResultCode */
#define PPTP_STOP_OK 1
#define PPTP_STOP_GENERAL_ERROR 2
struct
PptpStopSessionReply
{
__u8
resultCode
;
__u8
generalErrorCode
;
};
struct
PptpEchoRequest
{
__u32
identNumber
;
};
/* PptpEchoReplyResultCode */
#define PPTP_ECHO_OK 1
#define PPTP_ECHO_GENERAL_ERROR 2
struct
PptpEchoReply
{
__u32
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
{
__u16
callID
;
__u16
callSerialNumber
;
__u32
minBPS
;
__u32
maxBPS
;
__u32
bearerType
;
__u32
framingType
;
__u16
packetWindow
;
__u16
packetProcDelay
;
__u16
reserved1
;
__u16
phoneNumberLength
;
__u16
reserved2
;
__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
{
__u16
callID
;
__u16
peersCallID
;
__u8
resultCode
;
__u8
generalErrorCode
;
__u16
causeCode
;
__u32
connectSpeed
;
__u16
packetWindow
;
__u16
packetProcDelay
;
__u32
physChannelID
;
};
struct
PptpInCallRequest
{
__u16
callID
;
__u16
callSerialNumber
;
__u32
callBearerType
;
__u32
physChannelID
;
__u16
dialedNumberLength
;
__u16
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
{
__u16
callID
;
__u16
peersCallID
;
__u8
resultCode
;
__u8
generalErrorCode
;
__u16
packetWindow
;
__u16
packetProcDelay
;
__u16
reserved
;
};
struct
PptpInCallConnected
{
__u16
peersCallID
;
__u16
reserved
;
__u32
connectSpeed
;
__u16
packetWindow
;
__u16
packetProcDelay
;
__u32
callFramingType
;
};
struct
PptpClearCallRequest
{
__u16
callID
;
__u16
reserved
;
};
struct
PptpCallDisconnectNotify
{
__u16
callID
;
__u8
resultCode
;
__u8
generalErrorCode
;
__u16
causeCode
;
__u16
reserved
;
__u8
callStatistics
[
128
];
};
struct
PptpWanErrorNotify
{
__u16
peersCallID
;
__u16
reserved
;
__u32
crcErrors
;
__u32
framingErrors
;
__u32
hardwareOverRuns
;
__u32
bufferOverRuns
;
__u32
timeoutErrors
;
__u32
alignmentErrors
;
};
struct
PptpSetLinkInfo
{
__u16
peersCallID
;
__u16
reserved
;
__u32
sendAccm
;
__u32
recvAccm
;
};
struct
pptp_priv_data
{
__u16
call_id
;
__u16
mcall_id
;
__u16
pcall_id
;
};
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
;
};
extern
int
(
*
ip_nat_pptp_hook_outbound
)(
struct
sk_buff
**
pskb
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
,
struct
PptpControlHeader
*
ctlh
,
union
pptp_ctrl_union
*
pptpReq
);
extern
int
(
*
ip_nat_pptp_hook_inbound
)(
struct
sk_buff
**
pskb
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
,
struct
PptpControlHeader
*
ctlh
,
union
pptp_ctrl_union
*
pptpReq
);
extern
int
(
*
ip_nat_pptp_hook_exp_gre
)(
struct
ip_conntrack_expect
*
exp_orig
,
struct
ip_conntrack_expect
*
exp_reply
);
extern
void
(
*
ip_nat_pptp_hook_expectfn
)(
struct
ip_conntrack
*
ct
,
struct
ip_conntrack_expect
*
exp
);
#endif
/* __KERNEL__ */
#endif
/* _CONNTRACK_PPTP_H */
include/linux/netfilter_ipv4/ip_conntrack_proto_gre.h
0 → 100644
View file @
875bd5ab
#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
__u16
protocol
;
};
/* modified GRE header for PPTP */
struct
gre_hdr_pptp
{
__u8
flags
;
/* bitfield */
__u8
version
;
/* should be GRE_VERSION_PPTP */
__u16
protocol
;
/* should be GRE_PROTOCOL_PPTP */
__u16
payload_len
;
/* size of ppp payload, not inc. gre header */
__u16
call_id
;
/* peer's call_id for this session */
__u32
seq
;
/* sequence number. Present if S==1 */
__u32
ack
;
/* seq number of highest packet recieved by */
/* sender in this session */
};
/* this is part of ip_conntrack */
struct
ip_ct_gre
{
unsigned
int
stream_timeout
;
unsigned
int
timeout
;
};
#ifdef __KERNEL__
struct
ip_conntrack_expect
;
struct
ip_conntrack
;
/* structure for original <-> reply keymap */
struct
ip_ct_gre_keymap
{
struct
list_head
list
;
struct
ip_conntrack_tuple
tuple
;
};
/* add new tuple->key_reply pair to keymap */
int
ip_ct_gre_keymap_add
(
struct
ip_conntrack
*
ct
,
struct
ip_conntrack_tuple
*
t
,
int
reply
);
/* delete keymap entries */
void
ip_ct_gre_keymap_destroy
(
struct
ip_conntrack
*
ct
);
/* get pointer to gre key, if present */
static
inline
u_int32_t
*
gre_key
(
struct
gre_hdr
*
greh
)
{
if
(
!
greh
->
key
)
return
NULL
;
if
(
greh
->
csum
||
greh
->
routing
)
return
(
u_int32_t
*
)
(
greh
+
sizeof
(
*
greh
)
+
4
);
return
(
u_int32_t
*
)
(
greh
+
sizeof
(
*
greh
));
}
/* get pointer ot gre csum, if present */
static
inline
u_int16_t
*
gre_csum
(
struct
gre_hdr
*
greh
)
{
if
(
!
greh
->
csum
)
return
NULL
;
return
(
u_int16_t
*
)
(
greh
+
sizeof
(
*
greh
));
}
#endif
/* __KERNEL__ */
#endif
/* _CONNTRACK_PROTO_GRE_H */
include/linux/netfilter_ipv4/ip_conntrack_tuple.h
View file @
875bd5ab
...
...
@@ -28,6 +28,9 @@ union ip_conntrack_manip_proto
struct
{
u_int16_t
port
;
}
sctp
;
struct
{
u_int16_t
key
;
/* key is 32bit, pptp only uses 16 */
}
gre
;
};
/* The manipulable part of the tuple. */
...
...
@@ -61,6 +64,10 @@ struct ip_conntrack_tuple
struct
{
u_int16_t
port
;
}
sctp
;
struct
{
u_int16_t
key
;
/* key is 32bit,
* pptp only uses 16 */
}
gre
;
}
u
;
/* The protocol. */
...
...
include/linux/netfilter_ipv4/ip_nat_pptp.h
0 → 100644
View file @
875bd5ab
/* PPTP constants and structs */
#ifndef _NAT_PPTP_H
#define _NAT_PPTP_H
/* conntrack private data */
struct
ip_nat_pptp
{
u_int16_t
pns_call_id
;
/* NAT'ed PNS call id */
u_int16_t
pac_call_id
;
/* NAT'ed PAC call id */
};
#endif
/* _NAT_PPTP_H */
include/linux/netfilter_ipv6/ip6_tables.h
View file @
875bd5ab
...
...
@@ -455,6 +455,9 @@ extern unsigned int ip6t_do_table(struct sk_buff **pskb,
/* Check for an extension */
extern
int
ip6t_ext_hdr
(
u8
nexthdr
);
/* find specified header and get offset to it */
extern
int
ipv6_find_hdr
(
const
struct
sk_buff
*
skb
,
unsigned
int
*
offset
,
u8
target
);
#define IP6T_ALIGN(s) (((s) + (__alignof__(struct ip6t_entry)-1)) & ~(__alignof__(struct ip6t_entry)-1))
...
...
net/8021q/vlan_dev.c
View file @
875bd5ab
...
...
@@ -120,7 +120,7 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
unsigned
short
vid
;
struct
net_device_stats
*
stats
;
unsigned
short
vlan_TCI
;
unsigned
short
proto
;
__be16
proto
;
/* vlan_TCI = ntohs(get_unaligned(&vhdr->h_vlan_TCI)); */
vlan_TCI
=
ntohs
(
vhdr
->
h_vlan_TCI
);
...
...
net/ipv4/fib_trie.c
View file @
875bd5ab
...
...
@@ -43,7 +43,7 @@
* 2 of the License, or (at your option) any later version.
*/
#define VERSION "0.40
3
"
#define VERSION "0.40
4
"
#include <linux/config.h>
#include <asm/uaccess.h>
...
...
@@ -224,7 +224,7 @@ static inline int tkey_mismatch(t_key a, int offset, t_key b)
Consider a node 'n' and its parent 'tp'.
If n is a leaf, every bit in its key is significant. Its presence is
necessita
d
ed by path compression, since during a tree traversal (when
necessita
t
ed by path compression, since during a tree traversal (when
searching for a leaf - unless we are doing an insertion) we will completely
ignore all skipped bits we encounter. Thus we need to verify, at the end of
a potentially successful search, that we have indeed been walking the
...
...
@@ -836,11 +836,12 @@ static void trie_init(struct trie *t)
#endif
}
/* readside m
o
st use rcu_read_lock currently dump routines
/* readside m
u
st use rcu_read_lock currently dump routines
via get_fa_head and dump */
static
struct
leaf_info
*
find_leaf_info
(
struct
hlist_head
*
head
,
int
plen
)
static
struct
leaf_info
*
find_leaf_info
(
struct
leaf
*
l
,
int
plen
)
{
struct
hlist_head
*
head
=
&
l
->
list
;
struct
hlist_node
*
node
;
struct
leaf_info
*
li
;
...
...
@@ -853,7 +854,7 @@ static struct leaf_info *find_leaf_info(struct hlist_head *head, int plen)
static
inline
struct
list_head
*
get_fa_head
(
struct
leaf
*
l
,
int
plen
)
{
struct
leaf_info
*
li
=
find_leaf_info
(
&
l
->
list
,
plen
);
struct
leaf_info
*
li
=
find_leaf_info
(
l
,
plen
);
if
(
!
li
)
return
NULL
;
...
...
@@ -1248,7 +1249,7 @@ fn_trie_insert(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
}
/* should be c
l
alled with rcu_read_lock */
/* should be called with rcu_read_lock */
static
inline
int
check_leaf
(
struct
trie
*
t
,
struct
leaf
*
l
,
t_key
key
,
int
*
plen
,
const
struct
flowi
*
flp
,
struct
fib_result
*
res
)
...
...
@@ -1590,7 +1591,7 @@ fn_trie_delete(struct fib_table *tb, struct rtmsg *r, struct kern_rta *rta,
rtmsg_fib
(
RTM_DELROUTE
,
htonl
(
key
),
fa
,
plen
,
tb
->
tb_id
,
nlhdr
,
req
);
l
=
fib_find_node
(
t
,
key
);
li
=
find_leaf_info
(
&
l
->
list
,
plen
);
li
=
find_leaf_info
(
l
,
plen
);
list_del_rcu
(
&
fa
->
fa_list
);
...
...
@@ -1714,7 +1715,6 @@ static int fn_trie_flush(struct fib_table *tb)
t
->
revision
++
;
rcu_read_lock
();
for
(
h
=
0
;
(
l
=
nextleaf
(
t
,
l
))
!=
NULL
;
h
++
)
{
found
+=
trie_flush_leaf
(
t
,
l
);
...
...
@@ -1722,7 +1722,6 @@ static int fn_trie_flush(struct fib_table *tb)
trie_leaf_remove
(
t
,
ll
->
key
);
ll
=
l
;
}
rcu_read_unlock
();
if
(
ll
&&
hlist_empty
(
&
ll
->
list
))
trie_leaf_remove
(
t
,
ll
->
key
);
...
...
@@ -2029,7 +2028,7 @@ static struct node *fib_trie_get_first(struct fib_trie_iter *iter,
iter
->
tnode
=
(
struct
tnode
*
)
n
;
iter
->
trie
=
t
;
iter
->
index
=
0
;
iter
->
depth
=
0
;
iter
->
depth
=
1
;
return
n
;
}
return
NULL
;
...
...
@@ -2274,11 +2273,12 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
seq_puts
(
seq
,
"<local>:
\n
"
);
else
seq_puts
(
seq
,
"<main>:
\n
"
);
}
else
{
seq_indent
(
seq
,
iter
->
depth
-
1
);
seq_printf
(
seq
,
" +-- %d.%d.%d.%d/%d
\n
"
,
NIPQUAD
(
prf
),
tn
->
pos
);
}
}
seq_indent
(
seq
,
iter
->
depth
-
1
);
seq_printf
(
seq
,
" +-- %d.%d.%d.%d/%d %d %d %d
\n
"
,
NIPQUAD
(
prf
),
tn
->
pos
,
tn
->
bits
,
tn
->
full_children
,
tn
->
empty_children
);
}
else
{
struct
leaf
*
l
=
(
struct
leaf
*
)
n
;
int
i
;
...
...
@@ -2287,7 +2287,7 @@ static int fib_trie_seq_show(struct seq_file *seq, void *v)
seq_indent
(
seq
,
iter
->
depth
);
seq_printf
(
seq
,
" |-- %d.%d.%d.%d
\n
"
,
NIPQUAD
(
val
));
for
(
i
=
32
;
i
>=
0
;
i
--
)
{
struct
leaf_info
*
li
=
find_leaf_info
(
&
l
->
list
,
i
);
struct
leaf_info
*
li
=
find_leaf_info
(
l
,
i
);
if
(
li
)
{
struct
fib_alias
*
fa
;
list_for_each_entry_rcu
(
fa
,
&
li
->
falh
,
fa_list
)
{
...
...
@@ -2383,7 +2383,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
return
0
;
for
(
i
=
32
;
i
>=
0
;
i
--
)
{
struct
leaf_info
*
li
=
find_leaf_info
(
&
l
->
list
,
i
);
struct
leaf_info
*
li
=
find_leaf_info
(
l
,
i
);
struct
fib_alias
*
fa
;
u32
mask
,
prefix
;
...
...
net/ipv4/netfilter/Kconfig
View file @
875bd5ab
...
...
@@ -137,6 +137,22 @@ config IP_NF_AMANDA
To compile it as a module, choose M here. If unsure, say Y.
config IP_NF_PPTP
tristate 'PPTP protocol support'
help
This module adds support for PPTP (Point to Point Tunnelling
Protocol, RFC2637) conncection tracking and NAT.
If you are running PPTP sessions over a stateful firewall or NAT
box, you may want to enable this feature.
Please note that not all PPTP modes of operation are supported yet.
For more info, read top of the file
net/ipv4/netfilter/ip_conntrack_pptp.c
If you want to compile it as a module, say M here and read
Documentation/modules.txt. If unsure, say `N'.
config IP_NF_QUEUE
tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
help
...
...
@@ -621,6 +637,12 @@ config IP_NF_NAT_AMANDA
default IP_NF_NAT if IP_NF_AMANDA=y
default m if IP_NF_AMANDA=m
config IP_NF_NAT_PPTP
tristate
depends on IP_NF_NAT!=n && IP_NF_PPTP!=n
default IP_NF_NAT if IP_NF_PPTP=y
default m if IP_NF_PPTP=m
# mangle + specific targets
config IP_NF_MANGLE
tristate "Packet mangling"
...
...
net/ipv4/netfilter/Makefile
View file @
875bd5ab
...
...
@@ -6,6 +6,9 @@
ip_conntrack-objs
:=
ip_conntrack_standalone.o ip_conntrack_core.o ip_conntrack_proto_generic.o ip_conntrack_proto_tcp.o ip_conntrack_proto_udp.o ip_conntrack_proto_icmp.o
iptable_nat-objs
:=
ip_nat_standalone.o ip_nat_rule.o ip_nat_core.o ip_nat_helper.o ip_nat_proto_unknown.o ip_nat_proto_tcp.o ip_nat_proto_udp.o ip_nat_proto_icmp.o
ip_conntrack_pptp-objs
:=
ip_conntrack_helper_pptp.o ip_conntrack_proto_gre.o
ip_nat_pptp-objs
:=
ip_nat_helper_pptp.o ip_nat_proto_gre.o
# connection tracking
obj-$(CONFIG_IP_NF_CONNTRACK)
+=
ip_conntrack.o
...
...
@@ -17,6 +20,7 @@ obj-$(CONFIG_IP_NF_CONNTRACK_NETLINK) += ip_conntrack_netlink.o
obj-$(CONFIG_IP_NF_CT_PROTO_SCTP)
+=
ip_conntrack_proto_sctp.o
# connection tracking helpers
obj-$(CONFIG_IP_NF_PPTP)
+=
ip_conntrack_pptp.o
obj-$(CONFIG_IP_NF_AMANDA)
+=
ip_conntrack_amanda.o
obj-$(CONFIG_IP_NF_TFTP)
+=
ip_conntrack_tftp.o
obj-$(CONFIG_IP_NF_FTP)
+=
ip_conntrack_ftp.o
...
...
@@ -24,6 +28,7 @@ obj-$(CONFIG_IP_NF_IRC) += ip_conntrack_irc.o
obj-$(CONFIG_IP_NF_NETBIOS_NS)
+=
ip_conntrack_netbios_ns.o
# NAT helpers
obj-$(CONFIG_IP_NF_NAT_PPTP)
+=
ip_nat_pptp.o
obj-$(CONFIG_IP_NF_NAT_AMANDA)
+=
ip_nat_amanda.o
obj-$(CONFIG_IP_NF_NAT_TFTP)
+=
ip_nat_tftp.o
obj-$(CONFIG_IP_NF_NAT_FTP)
+=
ip_nat_ftp.o
...
...
net/ipv4/netfilter/ip_conntrack_core.c
View file @
875bd5ab
...
...
@@ -233,7 +233,7 @@ __ip_conntrack_expect_find(const struct ip_conntrack_tuple *tuple)
/* Just find a expectation corresponding to a tuple. */
struct
ip_conntrack_expect
*
ip_conntrack_expect_find
_get
(
const
struct
ip_conntrack_tuple
*
tuple
)
ip_conntrack_expect_find
(
const
struct
ip_conntrack_tuple
*
tuple
)
{
struct
ip_conntrack_expect
*
i
;
...
...
net/ipv4/netfilter/ip_conntrack_helper_pptp.c
0 → 100644
View file @
875bd5ab
/*
* ip_conntrack_pptp.c - Version 3.0
*
* Connection tracking support for PPTP (Point to Point Tunneling Protocol).
* PPTP is a a protocol for creating virtual private networks.
* It is a specification defined by Microsoft and some vendors
* working with Microsoft. PPTP is built on top of a modified
* version of the Internet Generic Routing Encapsulation Protocol.
* GRE is defined in RFC 1701 and RFC 1702. Documentation of
* PPTP can be found in RFC 2637
*
* (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
* Limitations:
* - We blindly assume that control connections are always
* established in PNS->PAC direction. This is a violation
* of RFFC2673
* - We can only support one single call within each session
*
* TODO:
* - testing of incoming PPTP calls
*
* Changes:
* 2002-02-05 - Version 1.3
* - Call ip_conntrack_unexpect_related() from
* pptp_destroy_siblings() to destroy expectations in case
* CALL_DISCONNECT_NOTIFY or tcp fin packet was seen
* (Philip Craig <philipc@snapgear.com>)
* - Add Version information at module loadtime
* 2002-02-10 - Version 1.6
* - move to C99 style initializers
* - remove second expectation if first arrives
* 2004-10-22 - Version 2.0
* - merge Mandrake's 2.6.x port with recent 2.6.x API changes
* - fix lots of linear skb assumptions from Mandrake's port
* 2005-06-10 - Version 2.1
* - use ip_conntrack_expect_free() instead of kfree() on the
* expect's (which are from the slab for quite some time)
* 2005-06-10 - Version 3.0
* - port helper to post-2.6.11 API changes,
* funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
* 2005-07-30 - Version 3.1
* - port helper to 2.6.13 API changes
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <net/checksum.h>
#include <net/tcp.h>
#include <linux/netfilter_ipv4/ip_conntrack.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
#define IP_CT_PPTP_VERSION "3.1"
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Harald Welte <laforge@gnumonks.org>"
);
MODULE_DESCRIPTION
(
"Netfilter connection tracking helper module for PPTP"
);
static
DEFINE_SPINLOCK
(
ip_pptp_lock
);
int
(
*
ip_nat_pptp_hook_outbound
)(
struct
sk_buff
**
pskb
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
,
struct
PptpControlHeader
*
ctlh
,
union
pptp_ctrl_union
*
pptpReq
);
int
(
*
ip_nat_pptp_hook_inbound
)(
struct
sk_buff
**
pskb
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
,
struct
PptpControlHeader
*
ctlh
,
union
pptp_ctrl_union
*
pptpReq
);
int
(
*
ip_nat_pptp_hook_exp_gre
)(
struct
ip_conntrack_expect
*
expect_orig
,
struct
ip_conntrack_expect
*
expect_reply
);
void
(
*
ip_nat_pptp_hook_expectfn
)(
struct
ip_conntrack
*
ct
,
struct
ip_conntrack_expect
*
exp
);
#if 0
/* PptpControlMessageType names */
const char *pptp_msg_name[] = {
"UNKNOWN_MESSAGE",
"START_SESSION_REQUEST",
"START_SESSION_REPLY",
"STOP_SESSION_REQUEST",
"STOP_SESSION_REPLY",
"ECHO_REQUEST",
"ECHO_REPLY",
"OUT_CALL_REQUEST",
"OUT_CALL_REPLY",
"IN_CALL_REQUEST",
"IN_CALL_REPLY",
"IN_CALL_CONNECT",
"CALL_CLEAR_REQUEST",
"CALL_DISCONNECT_NOTIFY",
"WAN_ERROR_NOTIFY",
"SET_LINK_INFO"
};
EXPORT_SYMBOL(pptp_msg_name);
#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
#else
#define DEBUGP(format, args...)
#endif
#define SECS *HZ
#define MINS * 60 SECS
#define HOURS * 60 MINS
#define PPTP_GRE_TIMEOUT (10 MINS)
#define PPTP_GRE_STREAM_TIMEOUT (5 HOURS)
static
void
pptp_expectfn
(
struct
ip_conntrack
*
ct
,
struct
ip_conntrack_expect
*
exp
)
{
DEBUGP
(
"increasing timeouts
\n
"
);
/* increase timeout of GRE data channel conntrack entry */
ct
->
proto
.
gre
.
timeout
=
PPTP_GRE_TIMEOUT
;
ct
->
proto
.
gre
.
stream_timeout
=
PPTP_GRE_STREAM_TIMEOUT
;
/* Can you see how rusty this code is, compared with the pre-2.6.11
* one? That's what happened to my shiny newnat of 2002 ;( -HW */
if
(
!
ip_nat_pptp_hook_expectfn
)
{
struct
ip_conntrack_tuple
inv_t
;
struct
ip_conntrack_expect
*
exp_other
;
/* obviously this tuple inversion only works until you do NAT */
invert_tuplepr
(
&
inv_t
,
&
exp
->
tuple
);
DEBUGP
(
"trying to unexpect other dir: "
);
DUMP_TUPLE
(
&
inv_t
);
exp_other
=
ip_conntrack_expect_find
(
&
inv_t
);
if
(
exp_other
)
{
/* delete other expectation. */
DEBUGP
(
"found
\n
"
);
ip_conntrack_unexpect_related
(
exp_other
);
ip_conntrack_expect_put
(
exp_other
);
}
else
{
DEBUGP
(
"not found
\n
"
);
}
}
else
{
/* we need more than simple inversion */
ip_nat_pptp_hook_expectfn
(
ct
,
exp
);
}
}
static
int
destroy_sibling_or_exp
(
const
struct
ip_conntrack_tuple
*
t
)
{
struct
ip_conntrack_tuple_hash
*
h
;
struct
ip_conntrack_expect
*
exp
;
DEBUGP
(
"trying to timeout ct or exp for tuple "
);
DUMP_TUPLE
(
t
);
h
=
ip_conntrack_find_get
(
t
,
NULL
);
if
(
h
)
{
struct
ip_conntrack
*
sibling
=
tuplehash_to_ctrack
(
h
);
DEBUGP
(
"setting timeout of conntrack %p to 0
\n
"
,
sibling
);
sibling
->
proto
.
gre
.
timeout
=
0
;
sibling
->
proto
.
gre
.
stream_timeout
=
0
;
/* refresh_acct will not modify counters if skb == NULL */
if
(
del_timer
(
&
sibling
->
timeout
))
sibling
->
timeout
.
function
((
unsigned
long
)
sibling
);
ip_conntrack_put
(
sibling
);
return
1
;
}
else
{
exp
=
ip_conntrack_expect_find
(
t
);
if
(
exp
)
{
DEBUGP
(
"unexpect_related of expect %p
\n
"
,
exp
);
ip_conntrack_unexpect_related
(
exp
);
ip_conntrack_expect_put
(
exp
);
return
1
;
}
}
return
0
;
}
/* timeout GRE data connections */
static
void
pptp_destroy_siblings
(
struct
ip_conntrack
*
ct
)
{
struct
ip_conntrack_tuple
t
;
/* Since ct->sibling_list has literally rusted away in 2.6.11,
* we now need another way to find out about our sibling
* contrack and expects... -HW */
/* try original (pns->pac) tuple */
memcpy
(
&
t
,
&
ct
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
,
sizeof
(
t
));
t
.
dst
.
protonum
=
IPPROTO_GRE
;
t
.
src
.
u
.
gre
.
key
=
htons
(
ct
->
help
.
ct_pptp_info
.
pns_call_id
);
t
.
dst
.
u
.
gre
.
key
=
htons
(
ct
->
help
.
ct_pptp_info
.
pac_call_id
);
if
(
!
destroy_sibling_or_exp
(
&
t
))
DEBUGP
(
"failed to timeout original pns->pac ct/exp
\n
"
);
/* try reply (pac->pns) tuple */
memcpy
(
&
t
,
&
ct
->
tuplehash
[
IP_CT_DIR_REPLY
].
tuple
,
sizeof
(
t
));
t
.
dst
.
protonum
=
IPPROTO_GRE
;
t
.
src
.
u
.
gre
.
key
=
htons
(
ct
->
help
.
ct_pptp_info
.
pac_call_id
);
t
.
dst
.
u
.
gre
.
key
=
htons
(
ct
->
help
.
ct_pptp_info
.
pns_call_id
);
if
(
!
destroy_sibling_or_exp
(
&
t
))
DEBUGP
(
"failed to timeout reply pac->pns ct/exp
\n
"
);
}
/* expect GRE connections (PNS->PAC and PAC->PNS direction) */
static
inline
int
exp_gre
(
struct
ip_conntrack
*
master
,
u_int32_t
seq
,
u_int16_t
callid
,
u_int16_t
peer_callid
)
{
struct
ip_conntrack_tuple
inv_tuple
;
struct
ip_conntrack_tuple
exp_tuples
[]
=
{
/* tuple in original direction, PNS->PAC */
{
.
src
=
{
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
.
src
.
ip
,
.
u
=
{
.
gre
=
{
.
key
=
peer_callid
}
}
},
.
dst
=
{
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
.
dst
.
ip
,
.
u
=
{
.
gre
=
{
.
key
=
callid
}
},
.
protonum
=
IPPROTO_GRE
},
},
/* tuple in reply direction, PAC->PNS */
{
.
src
=
{
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_REPLY
].
tuple
.
src
.
ip
,
.
u
=
{
.
gre
=
{
.
key
=
callid
}
}
},
.
dst
=
{
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_REPLY
].
tuple
.
dst
.
ip
,
.
u
=
{
.
gre
=
{
.
key
=
peer_callid
}
},
.
protonum
=
IPPROTO_GRE
},
}
};
struct
ip_conntrack_expect
*
exp_orig
,
*
exp_reply
;
int
ret
=
1
;
exp_orig
=
ip_conntrack_expect_alloc
(
master
);
if
(
exp_orig
==
NULL
)
goto
out
;
exp_reply
=
ip_conntrack_expect_alloc
(
master
);
if
(
exp_reply
==
NULL
)
goto
out_put_orig
;
memcpy
(
&
exp_orig
->
tuple
,
&
exp_tuples
[
0
],
sizeof
(
exp_orig
->
tuple
));
exp_orig
->
mask
.
src
.
ip
=
0xffffffff
;
exp_orig
->
mask
.
src
.
u
.
all
=
0
;
exp_orig
->
mask
.
dst
.
u
.
all
=
0
;
exp_orig
->
mask
.
dst
.
u
.
gre
.
key
=
0xffff
;
exp_orig
->
mask
.
dst
.
ip
=
0xffffffff
;
exp_orig
->
mask
.
dst
.
protonum
=
0xff
;
exp_orig
->
master
=
master
;
exp_orig
->
expectfn
=
pptp_expectfn
;
exp_orig
->
flags
=
0
;
exp_orig
->
dir
=
IP_CT_DIR_ORIGINAL
;
/* both expectations are identical apart from tuple */
memcpy
(
exp_reply
,
exp_orig
,
sizeof
(
*
exp_reply
));
memcpy
(
&
exp_reply
->
tuple
,
&
exp_tuples
[
1
],
sizeof
(
exp_reply
->
tuple
));
exp_reply
->
dir
=
!
exp_orig
->
dir
;
if
(
ip_nat_pptp_hook_exp_gre
)
ret
=
ip_nat_pptp_hook_exp_gre
(
exp_orig
,
exp_reply
);
else
{
DEBUGP
(
"calling expect_related PNS->PAC"
);
DUMP_TUPLE
(
&
exp_orig
->
tuple
);
if
(
ip_conntrack_expect_related
(
exp_orig
)
!=
0
)
{
DEBUGP
(
"cannot expect_related()
\n
"
);
goto
out_put_both
;
}
DEBUGP
(
"calling expect_related PAC->PNS"
);
DUMP_TUPLE
(
&
exp_reply
->
tuple
);
if
(
ip_conntrack_expect_related
(
exp_reply
)
!=
0
)
{
DEBUGP
(
"cannot expect_related()
\n
"
);
goto
out_unexpect_orig
;
}
/* Add GRE keymap entries */
if
(
ip_ct_gre_keymap_add
(
master
,
&
exp_reply
->
tuple
,
0
)
!=
0
)
{
DEBUGP
(
"cannot keymap_add() exp
\n
"
);
goto
out_unexpect_both
;
}
invert_tuplepr
(
&
inv_tuple
,
&
exp_reply
->
tuple
);
if
(
ip_ct_gre_keymap_add
(
master
,
&
inv_tuple
,
1
)
!=
0
)
{
ip_ct_gre_keymap_destroy
(
master
);
DEBUGP
(
"cannot keymap_add() exp_inv
\n
"
);
goto
out_unexpect_both
;
}
ret
=
0
;
}
out_put_both:
ip_conntrack_expect_put
(
exp_reply
);
out_put_orig:
ip_conntrack_expect_put
(
exp_orig
);
out:
return
ret
;
out_unexpect_both:
ip_conntrack_unexpect_related
(
exp_reply
);
out_unexpect_orig:
ip_conntrack_unexpect_related
(
exp_orig
);
goto
out_put_both
;
}
static
inline
int
pptp_inbound_pkt
(
struct
sk_buff
**
pskb
,
struct
tcphdr
*
tcph
,
unsigned
int
nexthdr_off
,
unsigned
int
datalen
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
)
{
struct
PptpControlHeader
_ctlh
,
*
ctlh
;
unsigned
int
reqlen
;
union
pptp_ctrl_union
_pptpReq
,
*
pptpReq
;
struct
ip_ct_pptp_master
*
info
=
&
ct
->
help
.
ct_pptp_info
;
u_int16_t
msg
,
*
cid
,
*
pcid
;
u_int32_t
seq
;
ctlh
=
skb_header_pointer
(
*
pskb
,
nexthdr_off
,
sizeof
(
_ctlh
),
&
_ctlh
);
if
(
!
ctlh
)
{
DEBUGP
(
"error during skb_header_pointer
\n
"
);
return
NF_ACCEPT
;
}
nexthdr_off
+=
sizeof
(
_ctlh
);
datalen
-=
sizeof
(
_ctlh
);
reqlen
=
datalen
;
if
(
reqlen
>
sizeof
(
*
pptpReq
))
reqlen
=
sizeof
(
*
pptpReq
);
pptpReq
=
skb_header_pointer
(
*
pskb
,
nexthdr_off
,
reqlen
,
&
_pptpReq
);
if
(
!
pptpReq
)
{
DEBUGP
(
"error during skb_header_pointer
\n
"
);
return
NF_ACCEPT
;
}
msg
=
ntohs
(
ctlh
->
messageType
);
DEBUGP
(
"inbound control message %s
\n
"
,
pptp_msg_name
[
msg
]);
switch
(
msg
)
{
case
PPTP_START_SESSION_REPLY
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
srep
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
/* server confirms new control session */
if
(
info
->
sstate
<
PPTP_SESSION_REQUESTED
)
{
DEBUGP
(
"%s without START_SESS_REQUEST
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
if
(
pptpReq
->
srep
.
resultCode
==
PPTP_START_OK
)
info
->
sstate
=
PPTP_SESSION_CONFIRMED
;
else
info
->
sstate
=
PPTP_SESSION_ERROR
;
break
;
case
PPTP_STOP_SESSION_REPLY
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
strep
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
/* server confirms end of control session */
if
(
info
->
sstate
>
PPTP_SESSION_STOPREQ
)
{
DEBUGP
(
"%s without STOP_SESS_REQUEST
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
if
(
pptpReq
->
strep
.
resultCode
==
PPTP_STOP_OK
)
info
->
sstate
=
PPTP_SESSION_NONE
;
else
info
->
sstate
=
PPTP_SESSION_ERROR
;
break
;
case
PPTP_OUT_CALL_REPLY
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
ocack
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
/* server accepted call, we now expect GRE frames */
if
(
info
->
sstate
!=
PPTP_SESSION_CONFIRMED
)
{
DEBUGP
(
"%s but no session
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
if
(
info
->
cstate
!=
PPTP_CALL_OUT_REQ
&&
info
->
cstate
!=
PPTP_CALL_OUT_CONF
)
{
DEBUGP
(
"%s without OUTCALL_REQ
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
if
(
pptpReq
->
ocack
.
resultCode
!=
PPTP_OUTCALL_CONNECT
)
{
info
->
cstate
=
PPTP_CALL_NONE
;
break
;
}
cid
=
&
pptpReq
->
ocack
.
callID
;
pcid
=
&
pptpReq
->
ocack
.
peersCallID
;
info
->
pac_call_id
=
ntohs
(
*
cid
);
if
(
htons
(
info
->
pns_call_id
)
!=
*
pcid
)
{
DEBUGP
(
"%s for unknown callid %u
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
pcid
));
break
;
}
DEBUGP
(
"%s, CID=%X, PCID=%X
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
cid
),
ntohs
(
*
pcid
));
info
->
cstate
=
PPTP_CALL_OUT_CONF
;
seq
=
ntohl
(
tcph
->
seq
)
+
sizeof
(
struct
pptp_pkt_hdr
)
+
sizeof
(
struct
PptpControlHeader
)
+
((
void
*
)
pcid
-
(
void
*
)
pptpReq
);
if
(
exp_gre
(
ct
,
seq
,
*
cid
,
*
pcid
)
!=
0
)
printk
(
"ip_conntrack_pptp: error during exp_gre
\n
"
);
break
;
case
PPTP_IN_CALL_REQUEST
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
icack
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
/* server tells us about incoming call request */
if
(
info
->
sstate
!=
PPTP_SESSION_CONFIRMED
)
{
DEBUGP
(
"%s but no session
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
pcid
=
&
pptpReq
->
icack
.
peersCallID
;
DEBUGP
(
"%s, PCID=%X
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
pcid
));
info
->
cstate
=
PPTP_CALL_IN_REQ
;
info
->
pac_call_id
=
ntohs
(
*
pcid
);
break
;
case
PPTP_IN_CALL_CONNECT
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
iccon
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
/* server tells us about incoming call established */
if
(
info
->
sstate
!=
PPTP_SESSION_CONFIRMED
)
{
DEBUGP
(
"%s but no session
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
if
(
info
->
sstate
!=
PPTP_CALL_IN_REP
&&
info
->
sstate
!=
PPTP_CALL_IN_CONF
)
{
DEBUGP
(
"%s but never sent IN_CALL_REPLY
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
pcid
=
&
pptpReq
->
iccon
.
peersCallID
;
cid
=
&
info
->
pac_call_id
;
if
(
info
->
pns_call_id
!=
ntohs
(
*
pcid
))
{
DEBUGP
(
"%s for unknown CallID %u
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
cid
));
break
;
}
DEBUGP
(
"%s, PCID=%X
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
pcid
));
info
->
cstate
=
PPTP_CALL_IN_CONF
;
/* we expect a GRE connection from PAC to PNS */
seq
=
ntohl
(
tcph
->
seq
)
+
sizeof
(
struct
pptp_pkt_hdr
)
+
sizeof
(
struct
PptpControlHeader
)
+
((
void
*
)
pcid
-
(
void
*
)
pptpReq
);
if
(
exp_gre
(
ct
,
seq
,
*
cid
,
*
pcid
)
!=
0
)
printk
(
"ip_conntrack_pptp: error during exp_gre
\n
"
);
break
;
case
PPTP_CALL_DISCONNECT_NOTIFY
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
disc
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
/* server confirms disconnect */
cid
=
&
pptpReq
->
disc
.
callID
;
DEBUGP
(
"%s, CID=%X
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
cid
));
info
->
cstate
=
PPTP_CALL_NONE
;
/* untrack this call id, unexpect GRE packets */
pptp_destroy_siblings
(
ct
);
break
;
case
PPTP_WAN_ERROR_NOTIFY
:
break
;
case
PPTP_ECHO_REQUEST
:
case
PPTP_ECHO_REPLY
:
/* I don't have to explain these ;) */
break
;
default:
DEBUGP
(
"invalid %s (TY=%d)
\n
"
,
(
msg
<=
PPTP_MSG_MAX
)
?
pptp_msg_name
[
msg
]
:
pptp_msg_name
[
0
],
msg
);
break
;
}
if
(
ip_nat_pptp_hook_inbound
)
return
ip_nat_pptp_hook_inbound
(
pskb
,
ct
,
ctinfo
,
ctlh
,
pptpReq
);
return
NF_ACCEPT
;
}
static
inline
int
pptp_outbound_pkt
(
struct
sk_buff
**
pskb
,
struct
tcphdr
*
tcph
,
unsigned
int
nexthdr_off
,
unsigned
int
datalen
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
)
{
struct
PptpControlHeader
_ctlh
,
*
ctlh
;
unsigned
int
reqlen
;
union
pptp_ctrl_union
_pptpReq
,
*
pptpReq
;
struct
ip_ct_pptp_master
*
info
=
&
ct
->
help
.
ct_pptp_info
;
u_int16_t
msg
,
*
cid
,
*
pcid
;
ctlh
=
skb_header_pointer
(
*
pskb
,
nexthdr_off
,
sizeof
(
_ctlh
),
&
_ctlh
);
if
(
!
ctlh
)
return
NF_ACCEPT
;
nexthdr_off
+=
sizeof
(
_ctlh
);
datalen
-=
sizeof
(
_ctlh
);
reqlen
=
datalen
;
if
(
reqlen
>
sizeof
(
*
pptpReq
))
reqlen
=
sizeof
(
*
pptpReq
);
pptpReq
=
skb_header_pointer
(
*
pskb
,
nexthdr_off
,
reqlen
,
&
_pptpReq
);
if
(
!
pptpReq
)
return
NF_ACCEPT
;
msg
=
ntohs
(
ctlh
->
messageType
);
DEBUGP
(
"outbound control message %s
\n
"
,
pptp_msg_name
[
msg
]);
switch
(
msg
)
{
case
PPTP_START_SESSION_REQUEST
:
/* client requests for new control session */
if
(
info
->
sstate
!=
PPTP_SESSION_NONE
)
{
DEBUGP
(
"%s but we already have one"
,
pptp_msg_name
[
msg
]);
}
info
->
sstate
=
PPTP_SESSION_REQUESTED
;
break
;
case
PPTP_STOP_SESSION_REQUEST
:
/* client requests end of control session */
info
->
sstate
=
PPTP_SESSION_STOPREQ
;
break
;
case
PPTP_OUT_CALL_REQUEST
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
ocreq
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
/* FIXME: break; */
}
/* client initiating connection to server */
if
(
info
->
sstate
!=
PPTP_SESSION_CONFIRMED
)
{
DEBUGP
(
"%s but no session
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
info
->
cstate
=
PPTP_CALL_OUT_REQ
;
/* track PNS call id */
cid
=
&
pptpReq
->
ocreq
.
callID
;
DEBUGP
(
"%s, CID=%X
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
cid
));
info
->
pns_call_id
=
ntohs
(
*
cid
);
break
;
case
PPTP_IN_CALL_REPLY
:
if
(
reqlen
<
sizeof
(
_pptpReq
.
icack
))
{
DEBUGP
(
"%s: short packet
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
/* client answers incoming call */
if
(
info
->
cstate
!=
PPTP_CALL_IN_REQ
&&
info
->
cstate
!=
PPTP_CALL_IN_REP
)
{
DEBUGP
(
"%s without incall_req
\n
"
,
pptp_msg_name
[
msg
]);
break
;
}
if
(
pptpReq
->
icack
.
resultCode
!=
PPTP_INCALL_ACCEPT
)
{
info
->
cstate
=
PPTP_CALL_NONE
;
break
;
}
pcid
=
&
pptpReq
->
icack
.
peersCallID
;
if
(
info
->
pac_call_id
!=
ntohs
(
*
pcid
))
{
DEBUGP
(
"%s for unknown call %u
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
pcid
));
break
;
}
DEBUGP
(
"%s, CID=%X
\n
"
,
pptp_msg_name
[
msg
],
ntohs
(
*
pcid
));
/* part two of the three-way handshake */
info
->
cstate
=
PPTP_CALL_IN_REP
;
info
->
pns_call_id
=
ntohs
(
pptpReq
->
icack
.
callID
);
break
;
case
PPTP_CALL_CLEAR_REQUEST
:
/* client requests hangup of call */
if
(
info
->
sstate
!=
PPTP_SESSION_CONFIRMED
)
{
DEBUGP
(
"CLEAR_CALL but no session
\n
"
);
break
;
}
/* FUTURE: iterate over all calls and check if
* call ID is valid. We don't do this without newnat,
* because we only know about last call */
info
->
cstate
=
PPTP_CALL_CLEAR_REQ
;
break
;
case
PPTP_SET_LINK_INFO
:
break
;
case
PPTP_ECHO_REQUEST
:
case
PPTP_ECHO_REPLY
:
/* I don't have to explain these ;) */
break
;
default:
DEBUGP
(
"invalid %s (TY=%d)
\n
"
,
(
msg
<=
PPTP_MSG_MAX
)
?
pptp_msg_name
[
msg
]
:
pptp_msg_name
[
0
],
msg
);
/* unknown: no need to create GRE masq table entry */
break
;
}
if
(
ip_nat_pptp_hook_outbound
)
return
ip_nat_pptp_hook_outbound
(
pskb
,
ct
,
ctinfo
,
ctlh
,
pptpReq
);
return
NF_ACCEPT
;
}
/* track caller id inside control connection, call expect_related */
static
int
conntrack_pptp_help
(
struct
sk_buff
**
pskb
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
)
{
struct
pptp_pkt_hdr
_pptph
,
*
pptph
;
struct
tcphdr
_tcph
,
*
tcph
;
u_int32_t
tcplen
=
(
*
pskb
)
->
len
-
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
;
u_int32_t
datalen
;
int
dir
=
CTINFO2DIR
(
ctinfo
);
struct
ip_ct_pptp_master
*
info
=
&
ct
->
help
.
ct_pptp_info
;
unsigned
int
nexthdr_off
;
int
oldsstate
,
oldcstate
;
int
ret
;
/* don't do any tracking before tcp handshake complete */
if
(
ctinfo
!=
IP_CT_ESTABLISHED
&&
ctinfo
!=
IP_CT_ESTABLISHED
+
IP_CT_IS_REPLY
)
{
DEBUGP
(
"ctinfo = %u, skipping
\n
"
,
ctinfo
);
return
NF_ACCEPT
;
}
nexthdr_off
=
(
*
pskb
)
->
nh
.
iph
->
ihl
*
4
;
tcph
=
skb_header_pointer
(
*
pskb
,
nexthdr_off
,
sizeof
(
_tcph
),
&
_tcph
);
BUG_ON
(
!
tcph
);
nexthdr_off
+=
tcph
->
doff
*
4
;
datalen
=
tcplen
-
tcph
->
doff
*
4
;
if
(
tcph
->
fin
||
tcph
->
rst
)
{
DEBUGP
(
"RST/FIN received, timeouting GRE
\n
"
);
/* can't do this after real newnat */
info
->
cstate
=
PPTP_CALL_NONE
;
/* untrack this call id, unexpect GRE packets */
pptp_destroy_siblings
(
ct
);
}
pptph
=
skb_header_pointer
(
*
pskb
,
nexthdr_off
,
sizeof
(
_pptph
),
&
_pptph
);
if
(
!
pptph
)
{
DEBUGP
(
"no full PPTP header, can't track
\n
"
);
return
NF_ACCEPT
;
}
nexthdr_off
+=
sizeof
(
_pptph
);
datalen
-=
sizeof
(
_pptph
);
/* if it's not a control message we can't do anything with it */
if
(
ntohs
(
pptph
->
packetType
)
!=
PPTP_PACKET_CONTROL
||
ntohl
(
pptph
->
magicCookie
)
!=
PPTP_MAGIC_COOKIE
)
{
DEBUGP
(
"not a control packet
\n
"
);
return
NF_ACCEPT
;
}
oldsstate
=
info
->
sstate
;
oldcstate
=
info
->
cstate
;
spin_lock_bh
(
&
ip_pptp_lock
);
/* FIXME: We just blindly assume that the control connection is always
* established from PNS->PAC. However, RFC makes no guarantee */
if
(
dir
==
IP_CT_DIR_ORIGINAL
)
/* client -> server (PNS -> PAC) */
ret
=
pptp_outbound_pkt
(
pskb
,
tcph
,
nexthdr_off
,
datalen
,
ct
,
ctinfo
);
else
/* server -> client (PAC -> PNS) */
ret
=
pptp_inbound_pkt
(
pskb
,
tcph
,
nexthdr_off
,
datalen
,
ct
,
ctinfo
);
DEBUGP
(
"sstate: %d->%d, cstate: %d->%d
\n
"
,
oldsstate
,
info
->
sstate
,
oldcstate
,
info
->
cstate
);
spin_unlock_bh
(
&
ip_pptp_lock
);
return
ret
;
}
/* control protocol helper */
static
struct
ip_conntrack_helper
pptp
=
{
.
list
=
{
NULL
,
NULL
},
.
name
=
"pptp"
,
.
me
=
THIS_MODULE
,
.
max_expected
=
2
,
.
timeout
=
5
*
60
,
.
tuple
=
{
.
src
=
{
.
ip
=
0
,
.
u
=
{
.
tcp
=
{
.
port
=
__constant_htons
(
PPTP_CONTROL_PORT
)
}
}
},
.
dst
=
{
.
ip
=
0
,
.
u
=
{
.
all
=
0
},
.
protonum
=
IPPROTO_TCP
}
},
.
mask
=
{
.
src
=
{
.
ip
=
0
,
.
u
=
{
.
tcp
=
{
.
port
=
0xffff
}
}
},
.
dst
=
{
.
ip
=
0
,
.
u
=
{
.
all
=
0
},
.
protonum
=
0xff
}
},
.
help
=
conntrack_pptp_help
};
extern
void
__exit
ip_ct_proto_gre_fini
(
void
);
extern
int
__init
ip_ct_proto_gre_init
(
void
);
/* ip_conntrack_pptp initialization */
static
int
__init
init
(
void
)
{
int
retcode
;
retcode
=
ip_ct_proto_gre_init
();
if
(
retcode
<
0
)
return
retcode
;
DEBUGP
(
" registering helper
\n
"
);
if
((
retcode
=
ip_conntrack_helper_register
(
&
pptp
)))
{
printk
(
KERN_ERR
"Unable to register conntrack application "
"helper for pptp: %d
\n
"
,
retcode
);
ip_ct_proto_gre_fini
();
return
retcode
;
}
printk
(
"ip_conntrack_pptp version %s loaded
\n
"
,
IP_CT_PPTP_VERSION
);
return
0
;
}
static
void
__exit
fini
(
void
)
{
ip_conntrack_helper_unregister
(
&
pptp
);
ip_ct_proto_gre_fini
();
printk
(
"ip_conntrack_pptp version %s unloaded
\n
"
,
IP_CT_PPTP_VERSION
);
}
module_init
(
init
);
module_exit
(
fini
);
EXPORT_SYMBOL
(
ip_nat_pptp_hook_outbound
);
EXPORT_SYMBOL
(
ip_nat_pptp_hook_inbound
);
EXPORT_SYMBOL
(
ip_nat_pptp_hook_exp_gre
);
EXPORT_SYMBOL
(
ip_nat_pptp_hook_expectfn
);
net/ipv4/netfilter/ip_conntrack_netlink.c
View file @
875bd5ab
...
...
@@ -1270,7 +1270,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
if
(
err
<
0
)
return
err
;
exp
=
ip_conntrack_expect_find
_get
(
&
tuple
);
exp
=
ip_conntrack_expect_find
(
&
tuple
);
if
(
!
exp
)
return
-
ENOENT
;
...
...
@@ -1318,7 +1318,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
return
err
;
/* bump usage count to 2 */
exp
=
ip_conntrack_expect_find
_get
(
&
tuple
);
exp
=
ip_conntrack_expect_find
(
&
tuple
);
if
(
!
exp
)
return
-
ENOENT
;
...
...
net/ipv4/netfilter/ip_conntrack_proto_gre.c
0 → 100644
View file @
875bd5ab
/*
* ip_conntrack_proto_gre.c - Version 3.0
*
* Connection tracking protocol helper module for GRE.
*
* GRE is a generic encapsulation protocol, which is generally not very
* suited for NAT, as it has no protocol-specific part as port numbers.
*
* It has an optional key field, which may help us distinguishing two
* connections between the same two hosts.
*
* GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
*
* PPTP is built on top of a modified version of GRE, and has a mandatory
* field called "CallID", which serves us for the same purpose as the key
* field in plain GRE.
*
* Documentation about PPTP can be found in RFC 2637
*
* (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/netfilter.h>
#include <linux/ip.h>
#include <linux/in.h>
#include <linux/list.h>
static
DEFINE_RWLOCK
(
ip_ct_gre_lock
);
#define ASSERT_READ_LOCK(x)
#define ASSERT_WRITE_LOCK(x)
#include <linux/netfilter_ipv4/listhelp.h>
#include <linux/netfilter_ipv4/ip_conntrack_protocol.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Harald Welte <laforge@gnumonks.org>"
);
MODULE_DESCRIPTION
(
"netfilter connection tracking protocol helper for GRE"
);
/* shamelessly stolen from ip_conntrack_proto_udp.c */
#define GRE_TIMEOUT (30*HZ)
#define GRE_STREAM_TIMEOUT (180*HZ)
#if 0
#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, __FUNCTION__, ## args)
#define DUMP_TUPLE_GRE(x) printk("%u.%u.%u.%u:0x%x -> %u.%u.%u.%u:0x%x\n", \
NIPQUAD((x)->src.ip), ntohs((x)->src.u.gre.key), \
NIPQUAD((x)->dst.ip), ntohs((x)->dst.u.gre.key))
#else
#define DEBUGP(x, args...)
#define DUMP_TUPLE_GRE(x)
#endif
/* GRE KEYMAP HANDLING FUNCTIONS */
static
LIST_HEAD
(
gre_keymap_list
);
static
inline
int
gre_key_cmpfn
(
const
struct
ip_ct_gre_keymap
*
km
,
const
struct
ip_conntrack_tuple
*
t
)
{
return
((
km
->
tuple
.
src
.
ip
==
t
->
src
.
ip
)
&&
(
km
->
tuple
.
dst
.
ip
==
t
->
dst
.
ip
)
&&
(
km
->
tuple
.
dst
.
protonum
==
t
->
dst
.
protonum
)
&&
(
km
->
tuple
.
dst
.
u
.
all
==
t
->
dst
.
u
.
all
));
}
/* look up the source key for a given tuple */
static
u_int32_t
gre_keymap_lookup
(
struct
ip_conntrack_tuple
*
t
)
{
struct
ip_ct_gre_keymap
*
km
;
u_int32_t
key
=
0
;
read_lock_bh
(
&
ip_ct_gre_lock
);
km
=
LIST_FIND
(
&
gre_keymap_list
,
gre_key_cmpfn
,
struct
ip_ct_gre_keymap
*
,
t
);
if
(
km
)
key
=
km
->
tuple
.
src
.
u
.
gre
.
key
;
read_unlock_bh
(
&
ip_ct_gre_lock
);
DEBUGP
(
"lookup src key 0x%x up key for "
,
key
);
DUMP_TUPLE_GRE
(
t
);
return
key
;
}
/* add a single keymap entry, associate with specified master ct */
int
ip_ct_gre_keymap_add
(
struct
ip_conntrack
*
ct
,
struct
ip_conntrack_tuple
*
t
,
int
reply
)
{
struct
ip_ct_gre_keymap
**
exist_km
,
*
km
,
*
old
;
if
(
!
ct
->
helper
||
strcmp
(
ct
->
helper
->
name
,
"pptp"
))
{
DEBUGP
(
"refusing to add GRE keymap to non-pptp session
\n
"
);
return
-
1
;
}
if
(
!
reply
)
exist_km
=
&
ct
->
help
.
ct_pptp_info
.
keymap_orig
;
else
exist_km
=
&
ct
->
help
.
ct_pptp_info
.
keymap_reply
;
if
(
*
exist_km
)
{
/* check whether it's a retransmission */
old
=
LIST_FIND
(
&
gre_keymap_list
,
gre_key_cmpfn
,
struct
ip_ct_gre_keymap
*
,
t
);
if
(
old
==
*
exist_km
)
{
DEBUGP
(
"retransmission
\n
"
);
return
0
;
}
DEBUGP
(
"trying to override keymap_%s for ct %p
\n
"
,
reply
?
"reply"
:
"orig"
,
ct
);
return
-
EEXIST
;
}
km
=
kmalloc
(
sizeof
(
*
km
),
GFP_ATOMIC
);
if
(
!
km
)
return
-
ENOMEM
;
memcpy
(
&
km
->
tuple
,
t
,
sizeof
(
*
t
));
*
exist_km
=
km
;
DEBUGP
(
"adding new entry %p: "
,
km
);
DUMP_TUPLE_GRE
(
&
km
->
tuple
);
write_lock_bh
(
&
ip_ct_gre_lock
);
list_append
(
&
gre_keymap_list
,
km
);
write_unlock_bh
(
&
ip_ct_gre_lock
);
return
0
;
}
/* destroy the keymap entries associated with specified master ct */
void
ip_ct_gre_keymap_destroy
(
struct
ip_conntrack
*
ct
)
{
DEBUGP
(
"entering for ct %p
\n
"
,
ct
);
if
(
!
ct
->
helper
||
strcmp
(
ct
->
helper
->
name
,
"pptp"
))
{
DEBUGP
(
"refusing to destroy GRE keymap to non-pptp session
\n
"
);
return
;
}
write_lock_bh
(
&
ip_ct_gre_lock
);
if
(
ct
->
help
.
ct_pptp_info
.
keymap_orig
)
{
DEBUGP
(
"removing %p from list
\n
"
,
ct
->
help
.
ct_pptp_info
.
keymap_orig
);
list_del
(
&
ct
->
help
.
ct_pptp_info
.
keymap_orig
->
list
);
kfree
(
ct
->
help
.
ct_pptp_info
.
keymap_orig
);
ct
->
help
.
ct_pptp_info
.
keymap_orig
=
NULL
;
}
if
(
ct
->
help
.
ct_pptp_info
.
keymap_reply
)
{
DEBUGP
(
"removing %p from list
\n
"
,
ct
->
help
.
ct_pptp_info
.
keymap_reply
);
list_del
(
&
ct
->
help
.
ct_pptp_info
.
keymap_reply
->
list
);
kfree
(
ct
->
help
.
ct_pptp_info
.
keymap_reply
);
ct
->
help
.
ct_pptp_info
.
keymap_reply
=
NULL
;
}
write_unlock_bh
(
&
ip_ct_gre_lock
);
}
/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
/* invert gre part of tuple */
static
int
gre_invert_tuple
(
struct
ip_conntrack_tuple
*
tuple
,
const
struct
ip_conntrack_tuple
*
orig
)
{
tuple
->
dst
.
u
.
gre
.
key
=
orig
->
src
.
u
.
gre
.
key
;
tuple
->
src
.
u
.
gre
.
key
=
orig
->
dst
.
u
.
gre
.
key
;
return
1
;
}
/* gre hdr info to tuple */
static
int
gre_pkt_to_tuple
(
const
struct
sk_buff
*
skb
,
unsigned
int
dataoff
,
struct
ip_conntrack_tuple
*
tuple
)
{
struct
gre_hdr_pptp
_pgrehdr
,
*
pgrehdr
;
u_int32_t
srckey
;
struct
gre_hdr
_grehdr
,
*
grehdr
;
/* first only delinearize old RFC1701 GRE header */
grehdr
=
skb_header_pointer
(
skb
,
dataoff
,
sizeof
(
_grehdr
),
&
_grehdr
);
if
(
!
grehdr
||
grehdr
->
version
!=
GRE_VERSION_PPTP
)
{
/* try to behave like "ip_conntrack_proto_generic" */
tuple
->
src
.
u
.
all
=
0
;
tuple
->
dst
.
u
.
all
=
0
;
return
1
;
}
/* PPTP header is variable length, only need up to the call_id field */
pgrehdr
=
skb_header_pointer
(
skb
,
dataoff
,
8
,
&
_pgrehdr
);
if
(
!
pgrehdr
)
return
1
;
if
(
ntohs
(
grehdr
->
protocol
)
!=
GRE_PROTOCOL_PPTP
)
{
DEBUGP
(
"GRE_VERSION_PPTP but unknown proto
\n
"
);
return
0
;
}
tuple
->
dst
.
u
.
gre
.
key
=
pgrehdr
->
call_id
;
srckey
=
gre_keymap_lookup
(
tuple
);
tuple
->
src
.
u
.
gre
.
key
=
srckey
;
return
1
;
}
/* print gre part of tuple */
static
int
gre_print_tuple
(
struct
seq_file
*
s
,
const
struct
ip_conntrack_tuple
*
tuple
)
{
return
seq_printf
(
s
,
"srckey=0x%x dstkey=0x%x "
,
ntohs
(
tuple
->
src
.
u
.
gre
.
key
),
ntohs
(
tuple
->
dst
.
u
.
gre
.
key
));
}
/* print private data for conntrack */
static
int
gre_print_conntrack
(
struct
seq_file
*
s
,
const
struct
ip_conntrack
*
ct
)
{
return
seq_printf
(
s
,
"timeout=%u, stream_timeout=%u "
,
(
ct
->
proto
.
gre
.
timeout
/
HZ
),
(
ct
->
proto
.
gre
.
stream_timeout
/
HZ
));
}
/* Returns verdict for packet, and may modify conntrack */
static
int
gre_packet
(
struct
ip_conntrack
*
ct
,
const
struct
sk_buff
*
skb
,
enum
ip_conntrack_info
conntrackinfo
)
{
/* If we've seen traffic both ways, this is a GRE connection.
* Extend timeout. */
if
(
ct
->
status
&
IPS_SEEN_REPLY
)
{
ip_ct_refresh_acct
(
ct
,
conntrackinfo
,
skb
,
ct
->
proto
.
gre
.
stream_timeout
);
/* Also, more likely to be important, and not a probe. */
set_bit
(
IPS_ASSURED_BIT
,
&
ct
->
status
);
}
else
ip_ct_refresh_acct
(
ct
,
conntrackinfo
,
skb
,
ct
->
proto
.
gre
.
timeout
);
return
NF_ACCEPT
;
}
/* Called when a new connection for this protocol found. */
static
int
gre_new
(
struct
ip_conntrack
*
ct
,
const
struct
sk_buff
*
skb
)
{
DEBUGP
(
": "
);
DUMP_TUPLE_GRE
(
&
ct
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
);
/* initialize to sane value. Ideally a conntrack helper
* (e.g. in case of pptp) is increasing them */
ct
->
proto
.
gre
.
stream_timeout
=
GRE_STREAM_TIMEOUT
;
ct
->
proto
.
gre
.
timeout
=
GRE_TIMEOUT
;
return
1
;
}
/* Called when a conntrack entry has already been removed from the hashes
* and is about to be deleted from memory */
static
void
gre_destroy
(
struct
ip_conntrack
*
ct
)
{
struct
ip_conntrack
*
master
=
ct
->
master
;
DEBUGP
(
" entering
\n
"
);
if
(
!
master
)
DEBUGP
(
"no master !?!
\n
"
);
else
ip_ct_gre_keymap_destroy
(
master
);
}
/* protocol helper struct */
static
struct
ip_conntrack_protocol
gre
=
{
.
proto
=
IPPROTO_GRE
,
.
name
=
"gre"
,
.
pkt_to_tuple
=
gre_pkt_to_tuple
,
.
invert_tuple
=
gre_invert_tuple
,
.
print_tuple
=
gre_print_tuple
,
.
print_conntrack
=
gre_print_conntrack
,
.
packet
=
gre_packet
,
.
new
=
gre_new
,
.
destroy
=
gre_destroy
,
.
me
=
THIS_MODULE
,
#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
.
tuple_to_nfattr
=
ip_ct_port_tuple_to_nfattr
,
.
nfattr_to_tuple
=
ip_ct_port_nfattr_to_tuple
,
#endif
};
/* ip_conntrack_proto_gre initialization */
int
__init
ip_ct_proto_gre_init
(
void
)
{
return
ip_conntrack_protocol_register
(
&
gre
);
}
void
__exit
ip_ct_proto_gre_fini
(
void
)
{
struct
list_head
*
pos
,
*
n
;
/* delete all keymap entries */
write_lock_bh
(
&
ip_ct_gre_lock
);
list_for_each_safe
(
pos
,
n
,
&
gre_keymap_list
)
{
DEBUGP
(
"deleting keymap %p at module unload time
\n
"
,
pos
);
list_del
(
pos
);
kfree
(
pos
);
}
write_unlock_bh
(
&
ip_ct_gre_lock
);
ip_conntrack_protocol_unregister
(
&
gre
);
}
EXPORT_SYMBOL
(
ip_ct_gre_keymap_add
);
EXPORT_SYMBOL
(
ip_ct_gre_keymap_destroy
);
net/ipv4/netfilter/ip_conntrack_standalone.c
View file @
875bd5ab
...
...
@@ -993,11 +993,11 @@ EXPORT_SYMBOL(ip_ct_refresh_acct);
EXPORT_SYMBOL
(
ip_conntrack_expect_alloc
);
EXPORT_SYMBOL
(
ip_conntrack_expect_put
);
EXPORT_SYMBOL_GPL
(
ip_conntrack_expect_find_get
);
EXPORT_SYMBOL_GPL
(
__ip_conntrack_expect_find
);
EXPORT_SYMBOL_GPL
(
ip_conntrack_expect_find
);
EXPORT_SYMBOL
(
ip_conntrack_expect_related
);
EXPORT_SYMBOL
(
ip_conntrack_unexpect_related
);
EXPORT_SYMBOL_GPL
(
ip_conntrack_expect_list
);
EXPORT_SYMBOL_GPL
(
__ip_conntrack_expect_find
);
EXPORT_SYMBOL_GPL
(
ip_ct_unlink_expect
);
EXPORT_SYMBOL
(
ip_conntrack_tuple_taken
);
...
...
net/ipv4/netfilter/ip_nat_core.c
View file @
875bd5ab
...
...
@@ -578,6 +578,8 @@ ip_nat_port_nfattr_to_range(struct nfattr *tb[], struct ip_nat_range *range)
return
ret
;
}
EXPORT_SYMBOL_GPL
(
ip_nat_port_nfattr_to_range
);
EXPORT_SYMBOL_GPL
(
ip_nat_port_range_to_nfattr
);
#endif
int
__init
ip_nat_init
(
void
)
...
...
net/ipv4/netfilter/ip_nat_helper_pptp.c
0 → 100644
View file @
875bd5ab
/*
* ip_nat_pptp.c - Version 3.0
*
* NAT support for PPTP (Point to Point Tunneling Protocol).
* PPTP is a a protocol for creating virtual private networks.
* It is a specification defined by Microsoft and some vendors
* working with Microsoft. PPTP is built on top of a modified
* version of the Internet Generic Routing Encapsulation Protocol.
* GRE is defined in RFC 1701 and RFC 1702. Documentation of
* PPTP can be found in RFC 2637
*
* (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
* TODO: - NAT to a unique tuple, not to TCP source port
* (needs netfilter tuple reservation)
*
* Changes:
* 2002-02-10 - Version 1.3
* - Use ip_nat_mangle_tcp_packet() because of cloned skb's
* in local connections (Philip Craig <philipc@snapgear.com>)
* - add checks for magicCookie and pptp version
* - make argument list of pptp_{out,in}bound_packet() shorter
* - move to C99 style initializers
* - print version number at module loadtime
* 2003-09-22 - Version 1.5
* - use SNATed tcp sourceport as callid, since we get called before
* TCP header is mangled (Philip Craig <philipc@snapgear.com>)
* 2004-10-22 - Version 2.0
* - kernel 2.6.x version
* 2005-06-10 - Version 3.0
* - kernel >= 2.6.11 version,
* funded by Oxcoda NetBox Blue (http://www.netboxblue.com/)
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/tcp.h>
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/netfilter_ipv4/ip_nat_helper.h>
#include <linux/netfilter_ipv4/ip_nat_pptp.h>
#include <linux/netfilter_ipv4/ip_conntrack_core.h>
#include <linux/netfilter_ipv4/ip_conntrack_helper.h>
#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
#include <linux/netfilter_ipv4/ip_conntrack_pptp.h>
#define IP_NAT_PPTP_VERSION "3.0"
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Harald Welte <laforge@gnumonks.org>"
);
MODULE_DESCRIPTION
(
"Netfilter NAT helper module for PPTP"
);
#if 0
extern const char *pptp_msg_name[];
#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
__FUNCTION__, ## args)
#else
#define DEBUGP(format, args...)
#endif
static
void
pptp_nat_expected
(
struct
ip_conntrack
*
ct
,
struct
ip_conntrack_expect
*
exp
)
{
struct
ip_conntrack
*
master
=
ct
->
master
;
struct
ip_conntrack_expect
*
other_exp
;
struct
ip_conntrack_tuple
t
;
struct
ip_ct_pptp_master
*
ct_pptp_info
;
struct
ip_nat_pptp
*
nat_pptp_info
;
ct_pptp_info
=
&
master
->
help
.
ct_pptp_info
;
nat_pptp_info
=
&
master
->
nat
.
help
.
nat_pptp_info
;
/* And here goes the grand finale of corrosion... */
if
(
exp
->
dir
==
IP_CT_DIR_ORIGINAL
)
{
DEBUGP
(
"we are PNS->PAC
\n
"
);
/* therefore, build tuple for PAC->PNS */
t
.
src
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_REPLY
].
tuple
.
src
.
ip
;
t
.
src
.
u
.
gre
.
key
=
htons
(
master
->
help
.
ct_pptp_info
.
pac_call_id
);
t
.
dst
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_REPLY
].
tuple
.
dst
.
ip
;
t
.
dst
.
u
.
gre
.
key
=
htons
(
master
->
help
.
ct_pptp_info
.
pns_call_id
);
t
.
dst
.
protonum
=
IPPROTO_GRE
;
}
else
{
DEBUGP
(
"we are PAC->PNS
\n
"
);
/* build tuple for PNS->PAC */
t
.
src
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
.
src
.
ip
;
t
.
src
.
u
.
gre
.
key
=
htons
(
master
->
nat
.
help
.
nat_pptp_info
.
pns_call_id
);
t
.
dst
.
ip
=
master
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
.
dst
.
ip
;
t
.
dst
.
u
.
gre
.
key
=
htons
(
master
->
nat
.
help
.
nat_pptp_info
.
pac_call_id
);
t
.
dst
.
protonum
=
IPPROTO_GRE
;
}
DEBUGP
(
"trying to unexpect other dir: "
);
DUMP_TUPLE
(
&
t
);
other_exp
=
ip_conntrack_expect_find
(
&
t
);
if
(
other_exp
)
{
ip_conntrack_unexpect_related
(
other_exp
);
ip_conntrack_expect_put
(
other_exp
);
DEBUGP
(
"success
\n
"
);
}
else
{
DEBUGP
(
"not found!
\n
"
);
}
ip_nat_follow_master
(
ct
,
exp
);
}
/* outbound packets == from PNS to PAC */
static
int
pptp_outbound_pkt
(
struct
sk_buff
**
pskb
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
,
struct
PptpControlHeader
*
ctlh
,
union
pptp_ctrl_union
*
pptpReq
)
{
struct
ip_ct_pptp_master
*
ct_pptp_info
=
&
ct
->
help
.
ct_pptp_info
;
struct
ip_nat_pptp
*
nat_pptp_info
=
&
ct
->
nat
.
help
.
nat_pptp_info
;
u_int16_t
msg
,
*
cid
=
NULL
,
new_callid
;
new_callid
=
htons
(
ct_pptp_info
->
pns_call_id
);
switch
(
msg
=
ntohs
(
ctlh
->
messageType
))
{
case
PPTP_OUT_CALL_REQUEST
:
cid
=
&
pptpReq
->
ocreq
.
callID
;
/* FIXME: ideally we would want to reserve a call ID
* here. current netfilter NAT core is not able to do
* this :( For now we use TCP source port. This breaks
* multiple calls within one control session */
/* save original call ID in nat_info */
nat_pptp_info
->
pns_call_id
=
ct_pptp_info
->
pns_call_id
;
/* don't use tcph->source since we are at a DSTmanip
* hook (e.g. PREROUTING) and pkt is not mangled yet */
new_callid
=
ct
->
tuplehash
[
IP_CT_DIR_REPLY
].
tuple
.
dst
.
u
.
tcp
.
port
;
/* save new call ID in ct info */
ct_pptp_info
->
pns_call_id
=
ntohs
(
new_callid
);
break
;
case
PPTP_IN_CALL_REPLY
:
cid
=
&
pptpReq
->
icreq
.
callID
;
break
;
case
PPTP_CALL_CLEAR_REQUEST
:
cid
=
&
pptpReq
->
clrreq
.
callID
;
break
;
default:
DEBUGP
(
"unknown outbound packet 0x%04x:%s
\n
"
,
msg
,
(
msg
<=
PPTP_MSG_MAX
)
?
pptp_msg_name
[
msg
]
:
pptp_msg_name
[
0
]);
/* fall through */
case
PPTP_SET_LINK_INFO
:
/* only need to NAT in case PAC is behind NAT box */
case
PPTP_START_SESSION_REQUEST
:
case
PPTP_START_SESSION_REPLY
:
case
PPTP_STOP_SESSION_REQUEST
:
case
PPTP_STOP_SESSION_REPLY
:
case
PPTP_ECHO_REQUEST
:
case
PPTP_ECHO_REPLY
:
/* no need to alter packet */
return
NF_ACCEPT
;
}
/* only OUT_CALL_REQUEST, IN_CALL_REPLY, CALL_CLEAR_REQUEST pass
* down to here */
IP_NF_ASSERT
(
cid
);
DEBUGP
(
"altering call id from 0x%04x to 0x%04x
\n
"
,
ntohs
(
*
cid
),
ntohs
(
new_callid
));
/* mangle packet */
if
(
ip_nat_mangle_tcp_packet
(
pskb
,
ct
,
ctinfo
,
(
void
*
)
cid
-
((
void
*
)
ctlh
-
sizeof
(
struct
pptp_pkt_hdr
)),
sizeof
(
new_callid
),
(
char
*
)
&
new_callid
,
sizeof
(
new_callid
))
==
0
)
return
NF_DROP
;
return
NF_ACCEPT
;
}
static
int
pptp_exp_gre
(
struct
ip_conntrack_expect
*
expect_orig
,
struct
ip_conntrack_expect
*
expect_reply
)
{
struct
ip_ct_pptp_master
*
ct_pptp_info
=
&
expect_orig
->
master
->
help
.
ct_pptp_info
;
struct
ip_nat_pptp
*
nat_pptp_info
=
&
expect_orig
->
master
->
nat
.
help
.
nat_pptp_info
;
struct
ip_conntrack
*
ct
=
expect_orig
->
master
;
struct
ip_conntrack_tuple
inv_t
;
struct
ip_conntrack_tuple
*
orig_t
,
*
reply_t
;
/* save original PAC call ID in nat_info */
nat_pptp_info
->
pac_call_id
=
ct_pptp_info
->
pac_call_id
;
/* alter expectation */
orig_t
=
&
ct
->
tuplehash
[
IP_CT_DIR_ORIGINAL
].
tuple
;
reply_t
=
&
ct
->
tuplehash
[
IP_CT_DIR_REPLY
].
tuple
;
/* alter expectation for PNS->PAC direction */
invert_tuplepr
(
&
inv_t
,
&
expect_orig
->
tuple
);
expect_orig
->
saved_proto
.
gre
.
key
=
htons
(
nat_pptp_info
->
pac_call_id
);
expect_orig
->
tuple
.
src
.
u
.
gre
.
key
=
htons
(
nat_pptp_info
->
pns_call_id
);
expect_orig
->
tuple
.
dst
.
u
.
gre
.
key
=
htons
(
ct_pptp_info
->
pac_call_id
);
inv_t
.
src
.
ip
=
reply_t
->
src
.
ip
;
inv_t
.
dst
.
ip
=
reply_t
->
dst
.
ip
;
inv_t
.
src
.
u
.
gre
.
key
=
htons
(
nat_pptp_info
->
pac_call_id
);
inv_t
.
dst
.
u
.
gre
.
key
=
htons
(
ct_pptp_info
->
pns_call_id
);
if
(
!
ip_conntrack_expect_related
(
expect_orig
))
{
DEBUGP
(
"successfully registered expect
\n
"
);
}
else
{
DEBUGP
(
"can't expect_related(expect_orig)
\n
"
);
return
1
;
}
/* alter expectation for PAC->PNS direction */
invert_tuplepr
(
&
inv_t
,
&
expect_reply
->
tuple
);
expect_reply
->
saved_proto
.
gre
.
key
=
htons
(
nat_pptp_info
->
pns_call_id
);
expect_reply
->
tuple
.
src
.
u
.
gre
.
key
=
htons
(
nat_pptp_info
->
pac_call_id
);
expect_reply
->
tuple
.
dst
.
u
.
gre
.
key
=
htons
(
ct_pptp_info
->
pns_call_id
);
inv_t
.
src
.
ip
=
orig_t
->
src
.
ip
;
inv_t
.
dst
.
ip
=
orig_t
->
dst
.
ip
;
inv_t
.
src
.
u
.
gre
.
key
=
htons
(
nat_pptp_info
->
pns_call_id
);
inv_t
.
dst
.
u
.
gre
.
key
=
htons
(
ct_pptp_info
->
pac_call_id
);
if
(
!
ip_conntrack_expect_related
(
expect_reply
))
{
DEBUGP
(
"successfully registered expect
\n
"
);
}
else
{
DEBUGP
(
"can't expect_related(expect_reply)
\n
"
);
ip_conntrack_unexpect_related
(
expect_orig
);
return
1
;
}
if
(
ip_ct_gre_keymap_add
(
ct
,
&
expect_reply
->
tuple
,
0
)
<
0
)
{
DEBUGP
(
"can't register original keymap
\n
"
);
ip_conntrack_unexpect_related
(
expect_orig
);
ip_conntrack_unexpect_related
(
expect_reply
);
return
1
;
}
if
(
ip_ct_gre_keymap_add
(
ct
,
&
inv_t
,
1
)
<
0
)
{
DEBUGP
(
"can't register reply keymap
\n
"
);
ip_conntrack_unexpect_related
(
expect_orig
);
ip_conntrack_unexpect_related
(
expect_reply
);
ip_ct_gre_keymap_destroy
(
ct
);
return
1
;
}
return
0
;
}
/* inbound packets == from PAC to PNS */
static
int
pptp_inbound_pkt
(
struct
sk_buff
**
pskb
,
struct
ip_conntrack
*
ct
,
enum
ip_conntrack_info
ctinfo
,
struct
PptpControlHeader
*
ctlh
,
union
pptp_ctrl_union
*
pptpReq
)
{
struct
ip_nat_pptp
*
nat_pptp_info
=
&
ct
->
nat
.
help
.
nat_pptp_info
;
u_int16_t
msg
,
new_cid
=
0
,
new_pcid
,
*
pcid
=
NULL
,
*
cid
=
NULL
;
int
ret
=
NF_ACCEPT
,
rv
;
new_pcid
=
htons
(
nat_pptp_info
->
pns_call_id
);
switch
(
msg
=
ntohs
(
ctlh
->
messageType
))
{
case
PPTP_OUT_CALL_REPLY
:
pcid
=
&
pptpReq
->
ocack
.
peersCallID
;
cid
=
&
pptpReq
->
ocack
.
callID
;
break
;
case
PPTP_IN_CALL_CONNECT
:
pcid
=
&
pptpReq
->
iccon
.
peersCallID
;
break
;
case
PPTP_IN_CALL_REQUEST
:
/* only need to nat in case PAC is behind NAT box */
break
;
case
PPTP_WAN_ERROR_NOTIFY
:
pcid
=
&
pptpReq
->
wanerr
.
peersCallID
;
break
;
case
PPTP_CALL_DISCONNECT_NOTIFY
:
pcid
=
&
pptpReq
->
disc
.
callID
;
break
;
case
PPTP_SET_LINK_INFO
:
pcid
=
&
pptpReq
->
setlink
.
peersCallID
;
break
;
default:
DEBUGP
(
"unknown inbound packet %s
\n
"
,
(
msg
<=
PPTP_MSG_MAX
)
?
pptp_msg_name
[
msg
]
:
pptp_msg_name
[
0
]);
/* fall through */
case
PPTP_START_SESSION_REQUEST
:
case
PPTP_START_SESSION_REPLY
:
case
PPTP_STOP_SESSION_REQUEST
:
case
PPTP_STOP_SESSION_REPLY
:
case
PPTP_ECHO_REQUEST
:
case
PPTP_ECHO_REPLY
:
/* no need to alter packet */
return
NF_ACCEPT
;
}
/* only OUT_CALL_REPLY, IN_CALL_CONNECT, IN_CALL_REQUEST,
* WAN_ERROR_NOTIFY, CALL_DISCONNECT_NOTIFY pass down here */
/* mangle packet */
IP_NF_ASSERT
(
pcid
);
DEBUGP
(
"altering peer call id from 0x%04x to 0x%04x
\n
"
,
ntohs
(
*
pcid
),
ntohs
(
new_pcid
));
rv
=
ip_nat_mangle_tcp_packet
(
pskb
,
ct
,
ctinfo
,
(
void
*
)
pcid
-
((
void
*
)
ctlh
-
sizeof
(
struct
pptp_pkt_hdr
)),
sizeof
(
new_pcid
),
(
char
*
)
&
new_pcid
,
sizeof
(
new_pcid
));
if
(
rv
!=
NF_ACCEPT
)
return
rv
;
if
(
new_cid
)
{
IP_NF_ASSERT
(
cid
);
DEBUGP
(
"altering call id from 0x%04x to 0x%04x
\n
"
,
ntohs
(
*
cid
),
ntohs
(
new_cid
));
rv
=
ip_nat_mangle_tcp_packet
(
pskb
,
ct
,
ctinfo
,
(
void
*
)
cid
-
((
void
*
)
ctlh
-
sizeof
(
struct
pptp_pkt_hdr
)),
sizeof
(
new_cid
),
(
char
*
)
&
new_cid
,
sizeof
(
new_cid
));
if
(
rv
!=
NF_ACCEPT
)
return
rv
;
}
/* check for earlier return value of 'switch' above */
if
(
ret
!=
NF_ACCEPT
)
return
ret
;
/* great, at least we don't need to resize packets */
return
NF_ACCEPT
;
}
extern
int
__init
ip_nat_proto_gre_init
(
void
);
extern
void
__exit
ip_nat_proto_gre_fini
(
void
);
static
int
__init
init
(
void
)
{
int
ret
;
DEBUGP
(
"%s: registering NAT helper
\n
"
,
__FILE__
);
ret
=
ip_nat_proto_gre_init
();
if
(
ret
<
0
)
return
ret
;
BUG_ON
(
ip_nat_pptp_hook_outbound
);
ip_nat_pptp_hook_outbound
=
&
pptp_outbound_pkt
;
BUG_ON
(
ip_nat_pptp_hook_inbound
);
ip_nat_pptp_hook_inbound
=
&
pptp_inbound_pkt
;
BUG_ON
(
ip_nat_pptp_hook_exp_gre
);
ip_nat_pptp_hook_exp_gre
=
&
pptp_exp_gre
;
BUG_ON
(
ip_nat_pptp_hook_expectfn
);
ip_nat_pptp_hook_expectfn
=
&
pptp_nat_expected
;
printk
(
"ip_nat_pptp version %s loaded
\n
"
,
IP_NAT_PPTP_VERSION
);
return
0
;
}
static
void
__exit
fini
(
void
)
{
DEBUGP
(
"cleanup_module
\n
"
);
ip_nat_pptp_hook_expectfn
=
NULL
;
ip_nat_pptp_hook_exp_gre
=
NULL
;
ip_nat_pptp_hook_inbound
=
NULL
;
ip_nat_pptp_hook_outbound
=
NULL
;
ip_nat_proto_gre_fini
();
/* Make sure noone calls it, meanwhile */
synchronize_net
();
printk
(
"ip_nat_pptp version %s unloaded
\n
"
,
IP_NAT_PPTP_VERSION
);
}
module_init
(
init
);
module_exit
(
fini
);
net/ipv4/netfilter/ip_nat_proto_gre.c
0 → 100644
View file @
875bd5ab
/*
* ip_nat_proto_gre.c - Version 2.0
*
* NAT protocol helper module for GRE.
*
* GRE is a generic encapsulation protocol, which is generally not very
* suited for NAT, as it has no protocol-specific part as port numbers.
*
* It has an optional key field, which may help us distinguishing two
* connections between the same two hosts.
*
* GRE is defined in RFC 1701 and RFC 1702, as well as RFC 2784
*
* PPTP is built on top of a modified version of GRE, and has a mandatory
* field called "CallID", which serves us for the same purpose as the key
* field in plain GRE.
*
* Documentation about PPTP can be found in RFC 2637
*
* (C) 2000-2005 by Harald Welte <laforge@gnumonks.org>
*
* Development of this code funded by Astaro AG (http://www.astaro.com/)
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/ip.h>
#include <linux/netfilter_ipv4/ip_nat.h>
#include <linux/netfilter_ipv4/ip_nat_rule.h>
#include <linux/netfilter_ipv4/ip_nat_protocol.h>
#include <linux/netfilter_ipv4/ip_conntrack_proto_gre.h>
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Harald Welte <laforge@gnumonks.org>"
);
MODULE_DESCRIPTION
(
"Netfilter NAT protocol helper module for GRE"
);
#if 0
#define DEBUGP(format, args...) printk(KERN_DEBUG "%s:%s: " format, __FILE__, \
__FUNCTION__, ## args)
#else
#define DEBUGP(x, args...)
#endif
/* is key in given range between min and max */
static
int
gre_in_range
(
const
struct
ip_conntrack_tuple
*
tuple
,
enum
ip_nat_manip_type
maniptype
,
const
union
ip_conntrack_manip_proto
*
min
,
const
union
ip_conntrack_manip_proto
*
max
)
{
u_int32_t
key
;
if
(
maniptype
==
IP_NAT_MANIP_SRC
)
key
=
tuple
->
src
.
u
.
gre
.
key
;
else
key
=
tuple
->
dst
.
u
.
gre
.
key
;
return
ntohl
(
key
)
>=
ntohl
(
min
->
gre
.
key
)
&&
ntohl
(
key
)
<=
ntohl
(
max
->
gre
.
key
);
}
/* generate unique tuple ... */
static
int
gre_unique_tuple
(
struct
ip_conntrack_tuple
*
tuple
,
const
struct
ip_nat_range
*
range
,
enum
ip_nat_manip_type
maniptype
,
const
struct
ip_conntrack
*
conntrack
)
{
static
u_int16_t
key
;
u_int16_t
*
keyptr
;
unsigned
int
min
,
i
,
range_size
;
if
(
maniptype
==
IP_NAT_MANIP_SRC
)
keyptr
=
&
tuple
->
src
.
u
.
gre
.
key
;
else
keyptr
=
&
tuple
->
dst
.
u
.
gre
.
key
;
if
(
!
(
range
->
flags
&
IP_NAT_RANGE_PROTO_SPECIFIED
))
{
DEBUGP
(
"%p: NATing GRE PPTP
\n
"
,
conntrack
);
min
=
1
;
range_size
=
0xffff
;
}
else
{
min
=
ntohl
(
range
->
min
.
gre
.
key
);
range_size
=
ntohl
(
range
->
max
.
gre
.
key
)
-
min
+
1
;
}
DEBUGP
(
"min = %u, range_size = %u
\n
"
,
min
,
range_size
);
for
(
i
=
0
;
i
<
range_size
;
i
++
,
key
++
)
{
*
keyptr
=
htonl
(
min
+
key
%
range_size
);
if
(
!
ip_nat_used_tuple
(
tuple
,
conntrack
))
return
1
;
}
DEBUGP
(
"%p: no NAT mapping
\n
"
,
conntrack
);
return
0
;
}
/* manipulate a GRE packet according to maniptype */
static
int
gre_manip_pkt
(
struct
sk_buff
**
pskb
,
unsigned
int
iphdroff
,
const
struct
ip_conntrack_tuple
*
tuple
,
enum
ip_nat_manip_type
maniptype
)
{
struct
gre_hdr
*
greh
;
struct
gre_hdr_pptp
*
pgreh
;
struct
iphdr
*
iph
=
(
struct
iphdr
*
)((
*
pskb
)
->
data
+
iphdroff
);
unsigned
int
hdroff
=
iphdroff
+
iph
->
ihl
*
4
;
/* pgreh includes two optional 32bit fields which are not required
* to be there. That's where the magic '8' comes from */
if
(
!
skb_make_writable
(
pskb
,
hdroff
+
sizeof
(
*
pgreh
)
-
8
))
return
0
;
greh
=
(
void
*
)(
*
pskb
)
->
data
+
hdroff
;
pgreh
=
(
struct
gre_hdr_pptp
*
)
greh
;
/* we only have destination manip of a packet, since 'source key'
* is not present in the packet itself */
if
(
maniptype
==
IP_NAT_MANIP_DST
)
{
/* key manipulation is always dest */
switch
(
greh
->
version
)
{
case
0
:
if
(
!
greh
->
key
)
{
DEBUGP
(
"can't nat GRE w/o key
\n
"
);
break
;
}
if
(
greh
->
csum
)
{
/* FIXME: Never tested this code... */
*
(
gre_csum
(
greh
))
=
ip_nat_cheat_check
(
~*
(
gre_key
(
greh
)),
tuple
->
dst
.
u
.
gre
.
key
,
*
(
gre_csum
(
greh
)));
}
*
(
gre_key
(
greh
))
=
tuple
->
dst
.
u
.
gre
.
key
;
break
;
case
GRE_VERSION_PPTP
:
DEBUGP
(
"call_id -> 0x%04x
\n
"
,
ntohl
(
tuple
->
dst
.
u
.
gre
.
key
));
pgreh
->
call_id
=
htons
(
ntohl
(
tuple
->
dst
.
u
.
gre
.
key
));
break
;
default:
DEBUGP
(
"can't nat unknown GRE version
\n
"
);
return
0
;
break
;
}
}
return
1
;
}
/* print out a nat tuple */
static
unsigned
int
gre_print
(
char
*
buffer
,
const
struct
ip_conntrack_tuple
*
match
,
const
struct
ip_conntrack_tuple
*
mask
)
{
unsigned
int
len
=
0
;
if
(
mask
->
src
.
u
.
gre
.
key
)
len
+=
sprintf
(
buffer
+
len
,
"srckey=0x%x "
,
ntohl
(
match
->
src
.
u
.
gre
.
key
));
if
(
mask
->
dst
.
u
.
gre
.
key
)
len
+=
sprintf
(
buffer
+
len
,
"dstkey=0x%x "
,
ntohl
(
match
->
src
.
u
.
gre
.
key
));
return
len
;
}
/* print a range of keys */
static
unsigned
int
gre_print_range
(
char
*
buffer
,
const
struct
ip_nat_range
*
range
)
{
if
(
range
->
min
.
gre
.
key
!=
0
||
range
->
max
.
gre
.
key
!=
0xFFFF
)
{
if
(
range
->
min
.
gre
.
key
==
range
->
max
.
gre
.
key
)
return
sprintf
(
buffer
,
"key 0x%x "
,
ntohl
(
range
->
min
.
gre
.
key
));
else
return
sprintf
(
buffer
,
"keys 0x%u-0x%u "
,
ntohl
(
range
->
min
.
gre
.
key
),
ntohl
(
range
->
max
.
gre
.
key
));
}
else
return
0
;
}
/* nat helper struct */
static
struct
ip_nat_protocol
gre
=
{
.
name
=
"GRE"
,
.
protonum
=
IPPROTO_GRE
,
.
manip_pkt
=
gre_manip_pkt
,
.
in_range
=
gre_in_range
,
.
unique_tuple
=
gre_unique_tuple
,
.
print
=
gre_print
,
.
print_range
=
gre_print_range
,
#if defined(CONFIG_IP_NF_CONNTRACK_NETLINK) || \
defined(CONFIG_IP_NF_CONNTRACK_NETLINK_MODULE)
.
range_to_nfattr
=
ip_nat_port_range_to_nfattr
,
.
nfattr_to_range
=
ip_nat_port_nfattr_to_range
,
#endif
};
int
__init
ip_nat_proto_gre_init
(
void
)
{
return
ip_nat_protocol_register
(
&
gre
);
}
void
__exit
ip_nat_proto_gre_fini
(
void
)
{
ip_nat_protocol_unregister
(
&
gre
);
}
net/ipv4/tcp_output.c
View file @
875bd5ab
...
...
@@ -461,9 +461,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
flags
=
TCP_SKB_CB
(
skb
)
->
flags
;
TCP_SKB_CB
(
skb
)
->
flags
=
flags
&
~
(
TCPCB_FLAG_FIN
|
TCPCB_FLAG_PSH
);
TCP_SKB_CB
(
buff
)
->
flags
=
flags
;
TCP_SKB_CB
(
buff
)
->
sacked
=
(
TCP_SKB_CB
(
skb
)
->
sacked
&
(
TCPCB_LOST
|
TCPCB_EVER_RETRANS
|
TCPCB_AT_TAIL
));
TCP_SKB_CB
(
buff
)
->
sacked
=
TCP_SKB_CB
(
skb
)
->
sacked
;
TCP_SKB_CB
(
skb
)
->
sacked
&=
~
TCPCB_AT_TAIL
;
if
(
!
skb_shinfo
(
skb
)
->
nr_frags
&&
skb
->
ip_summed
!=
CHECKSUM_HW
)
{
...
...
@@ -501,6 +499,12 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss
tcp_skb_pcount
(
buff
);
tp
->
packets_out
-=
diff
;
if
(
TCP_SKB_CB
(
skb
)
->
sacked
&
TCPCB_SACKED_ACKED
)
tp
->
sacked_out
-=
diff
;
if
(
TCP_SKB_CB
(
skb
)
->
sacked
&
TCPCB_SACKED_RETRANS
)
tp
->
retrans_out
-=
diff
;
if
(
TCP_SKB_CB
(
skb
)
->
sacked
&
TCPCB_LOST
)
{
tp
->
lost_out
-=
diff
;
tp
->
left_out
-=
diff
;
...
...
net/ipv6/netfilter/ip6_tables.c
View file @
875bd5ab
...
...
@@ -1955,6 +1955,57 @@ static void __exit fini(void)
#endif
}
/*
* find specified header up to transport protocol header.
* If found target header, the offset to the header is set to *offset
* and return 0. otherwise, return -1.
*
* Notes: - non-1st Fragment Header isn't skipped.
* - ESP header isn't skipped.
* - The target header may be trancated.
*/
int
ipv6_find_hdr
(
const
struct
sk_buff
*
skb
,
unsigned
int
*
offset
,
u8
target
)
{
unsigned
int
start
=
(
u8
*
)(
skb
->
nh
.
ipv6h
+
1
)
-
skb
->
data
;
u8
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
unsigned
int
len
=
skb
->
len
-
start
;
while
(
nexthdr
!=
target
)
{
struct
ipv6_opt_hdr
_hdr
,
*
hp
;
unsigned
int
hdrlen
;
if
((
!
ipv6_ext_hdr
(
nexthdr
))
||
nexthdr
==
NEXTHDR_NONE
)
return
-
1
;
hp
=
skb_header_pointer
(
skb
,
start
,
sizeof
(
_hdr
),
&
_hdr
);
if
(
hp
==
NULL
)
return
-
1
;
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
{
unsigned
short
_frag_off
,
*
fp
;
fp
=
skb_header_pointer
(
skb
,
start
+
offsetof
(
struct
frag_hdr
,
frag_off
),
sizeof
(
_frag_off
),
&
_frag_off
);
if
(
fp
==
NULL
)
return
-
1
;
if
(
ntohs
(
*
fp
)
&
~
0x7
)
return
-
1
;
hdrlen
=
8
;
}
else
if
(
nexthdr
==
NEXTHDR_AUTH
)
hdrlen
=
(
hp
->
hdrlen
+
2
)
<<
2
;
else
hdrlen
=
ipv6_optlen
(
hp
);
nexthdr
=
hp
->
nexthdr
;
len
-=
hdrlen
;
start
+=
hdrlen
;
}
*
offset
=
start
;
return
0
;
}
EXPORT_SYMBOL
(
ip6t_register_table
);
EXPORT_SYMBOL
(
ip6t_unregister_table
);
EXPORT_SYMBOL
(
ip6t_do_table
);
...
...
@@ -1963,6 +2014,7 @@ EXPORT_SYMBOL(ip6t_unregister_match);
EXPORT_SYMBOL
(
ip6t_register_target
);
EXPORT_SYMBOL
(
ip6t_unregister_target
);
EXPORT_SYMBOL
(
ip6t_ext_hdr
);
EXPORT_SYMBOL
(
ipv6_find_hdr
);
module_init
(
init
);
module_exit
(
fini
);
net/ipv6/netfilter/ip6t_ah.c
View file @
875bd5ab
...
...
@@ -48,92 +48,21 @@ match(const struct sk_buff *skb,
unsigned
int
protoff
,
int
*
hotdrop
)
{
struct
ip_auth_hdr
*
ah
=
NULL
,
_ah
;
struct
ip_auth_hdr
*
ah
,
_ah
;
const
struct
ip6t_ah
*
ahinfo
=
matchinfo
;
unsigned
int
temp
;
int
len
;
u8
nexthdr
;
unsigned
int
ptr
;
unsigned
int
hdrlen
=
0
;
/*DEBUGP("IPv6 AH entered\n");*/
/* if (opt->auth == 0) return 0;
* It does not filled on output */
/* type of the 1st exthdr */
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
/* pointer to the 1st exthdr */
ptr
=
sizeof
(
struct
ipv6hdr
);
/* available length */
len
=
skb
->
len
-
ptr
;
temp
=
0
;
while
(
ip6t_ext_hdr
(
nexthdr
))
{
struct
ipv6_opt_hdr
_hdr
,
*
hp
;
DEBUGP
(
"ipv6_ah header iteration
\n
"
);
/* Is there enough space for the next ext header? */
if
(
len
<
sizeof
(
struct
ipv6_opt_hdr
))
return
0
;
/* No more exthdr -> evaluate */
if
(
nexthdr
==
NEXTHDR_NONE
)
break
;
/* ESP -> evaluate */
if
(
nexthdr
==
NEXTHDR_ESP
)
break
;
hp
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_hdr
),
&
_hdr
);
BUG_ON
(
hp
==
NULL
);
/* Calculate the header length */
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
hdrlen
=
8
;
else
if
(
nexthdr
==
NEXTHDR_AUTH
)
hdrlen
=
(
hp
->
hdrlen
+
2
)
<<
2
;
else
hdrlen
=
ipv6_optlen
(
hp
);
/* AH -> evaluate */
if
(
nexthdr
==
NEXTHDR_AUTH
)
{
temp
|=
MASK_AH
;
break
;
}
/* set the flag */
switch
(
nexthdr
)
{
case
NEXTHDR_HOP
:
case
NEXTHDR_ROUTING
:
case
NEXTHDR_FRAGMENT
:
case
NEXTHDR_AUTH
:
case
NEXTHDR_DEST
:
break
;
default:
DEBUGP
(
"ipv6_ah match: unknown nextheader %u
\n
"
,
nexthdr
);
return
0
;
}
nexthdr
=
hp
->
nexthdr
;
len
-=
hdrlen
;
ptr
+=
hdrlen
;
if
(
ptr
>
skb
->
len
)
{
DEBUGP
(
"ipv6_ah: new pointer too large!
\n
"
);
break
;
}
}
/* AH header not found */
if
(
temp
!=
MASK_AH
)
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_AUTH
)
<
0
)
return
0
;
if
(
len
<
sizeof
(
struct
ip_auth_hdr
)){
ah
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_ah
),
&
_ah
);
if
(
ah
==
NULL
)
{
*
hotdrop
=
1
;
return
0
;
}
ah
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_ah
),
&
_ah
);
BUG_ON
(
ah
==
NULL
);
hdrlen
=
(
ah
->
hdrlen
+
2
)
<<
2
;
DEBUGP
(
"IPv6 AH LEN %u %u "
,
hdrlen
,
ah
->
hdrlen
);
DEBUGP
(
"RES %04X "
,
ah
->
reserved
);
...
...
net/ipv6/netfilter/ip6t_dst.c
View file @
875bd5ab
...
...
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb,
struct
ipv6_opt_hdr
_optsh
,
*
oh
;
const
struct
ip6t_opts
*
optinfo
=
matchinfo
;
unsigned
int
temp
;
unsigned
int
len
;
u8
nexthdr
;
unsigned
int
ptr
;
unsigned
int
hdrlen
=
0
;
unsigned
int
ret
=
0
;
...
...
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb,
u8
_optlen
,
*
lp
=
NULL
;
unsigned
int
optlen
;
/* type of the 1st exthdr */
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
/* pointer to the 1st exthdr */
ptr
=
sizeof
(
struct
ipv6hdr
);
/* available length */
len
=
skb
->
len
-
ptr
;
temp
=
0
;
while
(
ip6t_ext_hdr
(
nexthdr
))
{
struct
ipv6_opt_hdr
_hdr
,
*
hp
;
DEBUGP
(
"ipv6_opts header iteration
\n
"
);
/* Is there enough space for the next ext header? */
if
(
len
<
(
int
)
sizeof
(
struct
ipv6_opt_hdr
))
return
0
;
/* No more exthdr -> evaluate */
if
(
nexthdr
==
NEXTHDR_NONE
)
{
break
;
}
/* ESP -> evaluate */
if
(
nexthdr
==
NEXTHDR_ESP
)
{
break
;
}
hp
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_hdr
),
&
_hdr
);
BUG_ON
(
hp
==
NULL
);
/* Calculate the header length */
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
{
hdrlen
=
8
;
}
else
if
(
nexthdr
==
NEXTHDR_AUTH
)
hdrlen
=
(
hp
->
hdrlen
+
2
)
<<
2
;
else
hdrlen
=
ipv6_optlen
(
hp
);
/* OPTS -> evaluate */
#if HOPBYHOP
if
(
nexthdr
==
NEXTHDR_HOP
)
{
temp
|=
MASK_HOPOPTS
;
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_HOP
)
<
0
)
#else
if
(
nexthdr
==
NEXTHDR_DEST
)
{
temp
|=
MASK_DSTOPTS
;
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_DEST
)
<
0
)
#endif
break
;
}
return
0
;
/* set the flag */
switch
(
nexthdr
){
case
NEXTHDR_HOP
:
case
NEXTHDR_ROUTING
:
case
NEXTHDR_FRAGMENT
:
case
NEXTHDR_AUTH
:
case
NEXTHDR_DEST
:
break
;
default:
DEBUGP
(
"ipv6_opts match: unknown nextheader %u
\n
"
,
nexthdr
);
return
0
;
break
;
}
nexthdr
=
hp
->
nexthdr
;
len
-=
hdrlen
;
ptr
+=
hdrlen
;
if
(
ptr
>
skb
->
len
)
{
DEBUGP
(
"ipv6_opts: new pointer is too large!
\n
"
);
break
;
}
}
/* OPTIONS header not found */
#if HOPBYHOP
if
(
temp
!=
MASK_HOPOPTS
)
return
0
;
#else
if
(
temp
!=
MASK_DSTOPTS
)
return
0
;
#endif
if
(
len
<
(
int
)
sizeof
(
struct
ipv6_opt_hdr
)){
oh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_optsh
),
&
_optsh
);
if
(
oh
==
NULL
){
*
hotdrop
=
1
;
return
0
;
}
if
(
len
<
hdrlen
){
hdrlen
=
ipv6_optlen
(
oh
);
if
(
skb
->
len
-
ptr
<
hdrlen
){
/* Packet smaller than it's length field */
return
0
;
}
oh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_optsh
),
&
_optsh
);
BUG_ON
(
oh
==
NULL
);
DEBUGP
(
"IPv6 OPTS LEN %u %u "
,
hdrlen
,
oh
->
hdrlen
);
DEBUGP
(
"len %02X %04X %02X "
,
...
...
net/ipv6/netfilter/ip6t_esp.c
View file @
875bd5ab
...
...
@@ -48,87 +48,22 @@ match(const struct sk_buff *skb,
unsigned
int
protoff
,
int
*
hotdrop
)
{
struct
ip_esp_hdr
_esp
,
*
eh
=
NULL
;
struct
ip_esp_hdr
_esp
,
*
eh
;
const
struct
ip6t_esp
*
espinfo
=
matchinfo
;
unsigned
int
temp
;
int
len
;
u8
nexthdr
;
unsigned
int
ptr
;
/* Make sure this isn't an evil packet */
/*DEBUGP("ipv6_esp entered \n");*/
/* type of the 1st exthdr */
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
/* pointer to the 1st exthdr */
ptr
=
sizeof
(
struct
ipv6hdr
);
/* available length */
len
=
skb
->
len
-
ptr
;
temp
=
0
;
while
(
ip6t_ext_hdr
(
nexthdr
))
{
struct
ipv6_opt_hdr
_hdr
,
*
hp
;
int
hdrlen
;
DEBUGP
(
"ipv6_esp header iteration
\n
"
);
/* Is there enough space for the next ext header? */
if
(
len
<
sizeof
(
struct
ipv6_opt_hdr
))
return
0
;
/* No more exthdr -> evaluate */
if
(
nexthdr
==
NEXTHDR_NONE
)
break
;
/* ESP -> evaluate */
if
(
nexthdr
==
NEXTHDR_ESP
)
{
temp
|=
MASK_ESP
;
break
;
}
hp
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_hdr
),
&
_hdr
);
BUG_ON
(
hp
==
NULL
);
/* Calculate the header length */
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
hdrlen
=
8
;
else
if
(
nexthdr
==
NEXTHDR_AUTH
)
hdrlen
=
(
hp
->
hdrlen
+
2
)
<<
2
;
else
hdrlen
=
ipv6_optlen
(
hp
);
/* set the flag */
switch
(
nexthdr
)
{
case
NEXTHDR_HOP
:
case
NEXTHDR_ROUTING
:
case
NEXTHDR_FRAGMENT
:
case
NEXTHDR_AUTH
:
case
NEXTHDR_DEST
:
break
;
default:
DEBUGP
(
"ipv6_esp match: unknown nextheader %u
\n
"
,
nexthdr
);
return
0
;
}
nexthdr
=
hp
->
nexthdr
;
len
-=
hdrlen
;
ptr
+=
hdrlen
;
if
(
ptr
>
skb
->
len
)
{
DEBUGP
(
"ipv6_esp: new pointer too large!
\n
"
);
break
;
}
}
/* ESP header not found */
if
(
temp
!=
MASK_ESP
)
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_ESP
)
<
0
)
return
0
;
if
(
len
<
sizeof
(
struct
ip_esp_hdr
))
{
eh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_esp
),
&
_esp
);
if
(
eh
==
NULL
)
{
*
hotdrop
=
1
;
return
0
;
}
eh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_esp
),
&
_esp
);
BUG_ON
(
eh
==
NULL
);
DEBUGP
(
"IPv6 ESP SPI %u %08X
\n
"
,
ntohl
(
eh
->
spi
),
ntohl
(
eh
->
spi
));
return
(
eh
!=
NULL
)
...
...
net/ipv6/netfilter/ip6t_frag.c
View file @
875bd5ab
...
...
@@ -48,90 +48,18 @@ match(const struct sk_buff *skb,
unsigned
int
protoff
,
int
*
hotdrop
)
{
struct
frag_hdr
_frag
,
*
fh
=
NULL
;
struct
frag_hdr
_frag
,
*
fh
;
const
struct
ip6t_frag
*
fraginfo
=
matchinfo
;
unsigned
int
temp
;
int
len
;
u8
nexthdr
;
unsigned
int
ptr
;
unsigned
int
hdrlen
=
0
;
/* type of the 1st exthdr */
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
/* pointer to the 1st exthdr */
ptr
=
sizeof
(
struct
ipv6hdr
);
/* available length */
len
=
skb
->
len
-
ptr
;
temp
=
0
;
while
(
ip6t_ext_hdr
(
nexthdr
))
{
struct
ipv6_opt_hdr
_hdr
,
*
hp
;
DEBUGP
(
"ipv6_frag header iteration
\n
"
);
/* Is there enough space for the next ext header? */
if
(
len
<
(
int
)
sizeof
(
struct
ipv6_opt_hdr
))
return
0
;
/* No more exthdr -> evaluate */
if
(
nexthdr
==
NEXTHDR_NONE
)
{
break
;
}
/* ESP -> evaluate */
if
(
nexthdr
==
NEXTHDR_ESP
)
{
break
;
}
hp
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_hdr
),
&
_hdr
);
BUG_ON
(
hp
==
NULL
);
/* Calculate the header length */
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
{
hdrlen
=
8
;
}
else
if
(
nexthdr
==
NEXTHDR_AUTH
)
hdrlen
=
(
hp
->
hdrlen
+
2
)
<<
2
;
else
hdrlen
=
ipv6_optlen
(
hp
);
/* FRAG -> evaluate */
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
{
temp
|=
MASK_FRAGMENT
;
break
;
}
/* set the flag */
switch
(
nexthdr
){
case
NEXTHDR_HOP
:
case
NEXTHDR_ROUTING
:
case
NEXTHDR_FRAGMENT
:
case
NEXTHDR_AUTH
:
case
NEXTHDR_DEST
:
break
;
default:
DEBUGP
(
"ipv6_frag match: unknown nextheader %u
\n
"
,
nexthdr
);
return
0
;
break
;
}
nexthdr
=
hp
->
nexthdr
;
len
-=
hdrlen
;
ptr
+=
hdrlen
;
if
(
ptr
>
skb
->
len
)
{
DEBUGP
(
"ipv6_frag: new pointer too large!
\n
"
);
break
;
}
}
/* FRAG header not found */
if
(
temp
!=
MASK_FRAGMENT
)
return
0
;
if
(
len
<
sizeof
(
struct
frag_hdr
)){
*
hotdrop
=
1
;
return
0
;
}
fh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_frag
),
&
_frag
);
BUG_ON
(
fh
==
NULL
);
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_FRAGMENT
)
<
0
)
return
0
;
fh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_frag
),
&
_frag
);
if
(
fh
==
NULL
){
*
hotdrop
=
1
;
return
0
;
}
DEBUGP
(
"INFO %04X "
,
fh
->
frag_off
);
DEBUGP
(
"OFFSET %04X "
,
ntohs
(
fh
->
frag_off
)
&
~
0x7
);
...
...
net/ipv6/netfilter/ip6t_hbh.c
View file @
875bd5ab
...
...
@@ -63,8 +63,6 @@ match(const struct sk_buff *skb,
struct
ipv6_opt_hdr
_optsh
,
*
oh
;
const
struct
ip6t_opts
*
optinfo
=
matchinfo
;
unsigned
int
temp
;
unsigned
int
len
;
u8
nexthdr
;
unsigned
int
ptr
;
unsigned
int
hdrlen
=
0
;
unsigned
int
ret
=
0
;
...
...
@@ -72,97 +70,25 @@ match(const struct sk_buff *skb,
u8
_optlen
,
*
lp
=
NULL
;
unsigned
int
optlen
;
/* type of the 1st exthdr */
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
/* pointer to the 1st exthdr */
ptr
=
sizeof
(
struct
ipv6hdr
);
/* available length */
len
=
skb
->
len
-
ptr
;
temp
=
0
;
while
(
ip6t_ext_hdr
(
nexthdr
))
{
struct
ipv6_opt_hdr
_hdr
,
*
hp
;
DEBUGP
(
"ipv6_opts header iteration
\n
"
);
/* Is there enough space for the next ext header? */
if
(
len
<
(
int
)
sizeof
(
struct
ipv6_opt_hdr
))
return
0
;
/* No more exthdr -> evaluate */
if
(
nexthdr
==
NEXTHDR_NONE
)
{
break
;
}
/* ESP -> evaluate */
if
(
nexthdr
==
NEXTHDR_ESP
)
{
break
;
}
hp
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_hdr
),
&
_hdr
);
BUG_ON
(
hp
==
NULL
);
/* Calculate the header length */
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
{
hdrlen
=
8
;
}
else
if
(
nexthdr
==
NEXTHDR_AUTH
)
hdrlen
=
(
hp
->
hdrlen
+
2
)
<<
2
;
else
hdrlen
=
ipv6_optlen
(
hp
);
/* OPTS -> evaluate */
#if HOPBYHOP
if
(
nexthdr
==
NEXTHDR_HOP
)
{
temp
|=
MASK_HOPOPTS
;
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_HOP
)
<
0
)
#else
if
(
nexthdr
==
NEXTHDR_DEST
)
{
temp
|=
MASK_DSTOPTS
;
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_DEST
)
<
0
)
#endif
break
;
}
return
0
;
/* set the flag */
switch
(
nexthdr
){
case
NEXTHDR_HOP
:
case
NEXTHDR_ROUTING
:
case
NEXTHDR_FRAGMENT
:
case
NEXTHDR_AUTH
:
case
NEXTHDR_DEST
:
break
;
default:
DEBUGP
(
"ipv6_opts match: unknown nextheader %u
\n
"
,
nexthdr
);
return
0
;
break
;
}
nexthdr
=
hp
->
nexthdr
;
len
-=
hdrlen
;
ptr
+=
hdrlen
;
if
(
ptr
>
skb
->
len
)
{
DEBUGP
(
"ipv6_opts: new pointer is too large!
\n
"
);
break
;
}
}
/* OPTIONS header not found */
#if HOPBYHOP
if
(
temp
!=
MASK_HOPOPTS
)
return
0
;
#else
if
(
temp
!=
MASK_DSTOPTS
)
return
0
;
#endif
if
(
len
<
(
int
)
sizeof
(
struct
ipv6_opt_hdr
)){
oh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_optsh
),
&
_optsh
);
if
(
oh
==
NULL
){
*
hotdrop
=
1
;
return
0
;
}
if
(
len
<
hdrlen
){
hdrlen
=
ipv6_optlen
(
oh
);
if
(
skb
->
len
-
ptr
<
hdrlen
){
/* Packet smaller than it's length field */
return
0
;
}
oh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_optsh
),
&
_optsh
);
BUG_ON
(
oh
==
NULL
);
DEBUGP
(
"IPv6 OPTS LEN %u %u "
,
hdrlen
,
oh
->
hdrlen
);
DEBUGP
(
"len %02X %04X %02X "
,
...
...
net/ipv6/netfilter/ip6t_rt.c
View file @
875bd5ab
...
...
@@ -50,98 +50,29 @@ match(const struct sk_buff *skb,
unsigned
int
protoff
,
int
*
hotdrop
)
{
struct
ipv6_rt_hdr
_route
,
*
rh
=
NULL
;
struct
ipv6_rt_hdr
_route
,
*
rh
;
const
struct
ip6t_rt
*
rtinfo
=
matchinfo
;
unsigned
int
temp
;
unsigned
int
len
;
u8
nexthdr
;
unsigned
int
ptr
;
unsigned
int
hdrlen
=
0
;
unsigned
int
ret
=
0
;
struct
in6_addr
*
ap
,
_addr
;
/* type of the 1st exthdr */
nexthdr
=
skb
->
nh
.
ipv6h
->
nexthdr
;
/* pointer to the 1st exthdr */
ptr
=
sizeof
(
struct
ipv6hdr
);
/* available length */
len
=
skb
->
len
-
ptr
;
temp
=
0
;
if
(
ipv6_find_hdr
(
skb
,
&
ptr
,
NEXTHDR_ROUTING
)
<
0
)
return
0
;
while
(
ip6t_ext_hdr
(
nexthdr
))
{
struct
ipv6_opt_hdr
_hdr
,
*
hp
;
DEBUGP
(
"ipv6_rt header iteration
\n
"
);
/* Is there enough space for the next ext header? */
if
(
len
<
(
int
)
sizeof
(
struct
ipv6_opt_hdr
))
return
0
;
/* No more exthdr -> evaluate */
if
(
nexthdr
==
NEXTHDR_NONE
)
{
break
;
}
/* ESP -> evaluate */
if
(
nexthdr
==
NEXTHDR_ESP
)
{
break
;
}
hp
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_hdr
),
&
_hdr
);
BUG_ON
(
hp
==
NULL
);
/* Calculate the header length */
if
(
nexthdr
==
NEXTHDR_FRAGMENT
)
{
hdrlen
=
8
;
}
else
if
(
nexthdr
==
NEXTHDR_AUTH
)
hdrlen
=
(
hp
->
hdrlen
+
2
)
<<
2
;
else
hdrlen
=
ipv6_optlen
(
hp
);
/* ROUTING -> evaluate */
if
(
nexthdr
==
NEXTHDR_ROUTING
)
{
temp
|=
MASK_ROUTING
;
break
;
}
/* set the flag */
switch
(
nexthdr
){
case
NEXTHDR_HOP
:
case
NEXTHDR_ROUTING
:
case
NEXTHDR_FRAGMENT
:
case
NEXTHDR_AUTH
:
case
NEXTHDR_DEST
:
break
;
default:
DEBUGP
(
"ipv6_rt match: unknown nextheader %u
\n
"
,
nexthdr
);
return
0
;
break
;
}
nexthdr
=
hp
->
nexthdr
;
len
-=
hdrlen
;
ptr
+=
hdrlen
;
if
(
ptr
>
skb
->
len
)
{
DEBUGP
(
"ipv6_rt: new pointer is too large!
\n
"
);
break
;
}
}
/* ROUTING header not found */
if
(
temp
!=
MASK_ROUTING
)
return
0
;
if
(
len
<
(
int
)
sizeof
(
struct
ipv6_rt_hdr
)){
rh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_route
),
&
_route
);
if
(
rh
==
NULL
){
*
hotdrop
=
1
;
return
0
;
}
if
(
len
<
hdrlen
){
hdrlen
=
ipv6_optlen
(
rh
);
if
(
skb
->
len
-
ptr
<
hdrlen
){
/* Pcket smaller than its length field */
return
0
;
}
rh
=
skb_header_pointer
(
skb
,
ptr
,
sizeof
(
_route
),
&
_route
);
BUG_ON
(
rh
==
NULL
);
DEBUGP
(
"IPv6 RT LEN %u %u "
,
hdrlen
,
rh
->
hdrlen
);
DEBUGP
(
"TYPE %04X "
,
rh
->
type
);
DEBUGP
(
"SGS_LEFT %u %02X
\n
"
,
rh
->
segments_left
,
rh
->
segments_left
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment