Commit 4c651756 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller

[NETFILTER]: PPTP conntrack: consolidate header parsing

Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a1073406
...@@ -291,60 +291,21 @@ exp_gre(struct ip_conntrack *ct, ...@@ -291,60 +291,21 @@ exp_gre(struct ip_conntrack *ct,
goto out_put_both; goto out_put_both;
} }
static const unsigned int pptp_msg_size[] = {
[PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest),
[PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply),
[PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest),
[PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply),
[PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest),
[PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply),
[PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest),
[PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply),
[PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected),
[PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest),
[PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify),
[PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify),
[PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo),
};
static inline int static inline int
pptp_inbound_pkt(struct sk_buff **pskb, pptp_inbound_pkt(struct sk_buff **pskb,
struct tcphdr *tcph, struct PptpControlHeader *ctlh,
unsigned int nexthdr_off, union pptp_ctrl_union *pptpReq,
unsigned int datalen, unsigned int reqlen,
struct ip_conntrack *ct, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo) 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; struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
u_int16_t msg; u_int16_t msg;
__be16 cid, pcid; __be16 cid, pcid;
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); msg = ntohs(ctlh->messageType);
DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
return NF_ACCEPT;
switch (msg) { switch (msg) {
case PPTP_START_SESSION_REPLY: case PPTP_START_SESSION_REPLY:
/* server confirms new control session */ /* server confirms new control session */
...@@ -480,38 +441,19 @@ pptp_inbound_pkt(struct sk_buff **pskb, ...@@ -480,38 +441,19 @@ pptp_inbound_pkt(struct sk_buff **pskb,
static inline int static inline int
pptp_outbound_pkt(struct sk_buff **pskb, pptp_outbound_pkt(struct sk_buff **pskb,
struct tcphdr *tcph, struct PptpControlHeader *ctlh,
unsigned int nexthdr_off, union pptp_ctrl_union *pptpReq,
unsigned int datalen, unsigned int reqlen,
struct ip_conntrack *ct, struct ip_conntrack *ct,
enum ip_conntrack_info ctinfo) 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; struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
u_int16_t msg; u_int16_t msg;
__be16 cid, pcid; __be16 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); msg = ntohs(ctlh->messageType);
DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
return NF_ACCEPT;
switch (msg) { switch (msg) {
case PPTP_START_SESSION_REQUEST: case PPTP_START_SESSION_REQUEST:
/* client requests for new control session */ /* client requests for new control session */
...@@ -593,6 +535,21 @@ pptp_outbound_pkt(struct sk_buff **pskb, ...@@ -593,6 +535,21 @@ pptp_outbound_pkt(struct sk_buff **pskb,
return NF_ACCEPT; return NF_ACCEPT;
} }
static const unsigned int pptp_msg_size[] = {
[PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest),
[PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply),
[PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest),
[PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply),
[PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest),
[PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply),
[PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest),
[PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply),
[PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected),
[PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest),
[PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify),
[PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify),
[PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo),
};
/* track caller id inside control connection, call expect_related */ /* track caller id inside control connection, call expect_related */
static int static int
...@@ -600,16 +557,17 @@ conntrack_pptp_help(struct sk_buff **pskb, ...@@ -600,16 +557,17 @@ conntrack_pptp_help(struct sk_buff **pskb,
struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) 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); int dir = CTINFO2DIR(ctinfo);
struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
unsigned int nexthdr_off; struct tcphdr _tcph, *tcph;
struct pptp_pkt_hdr _pptph, *pptph;
struct PptpControlHeader _ctlh, *ctlh;
union pptp_ctrl_union _pptpReq, *pptpReq;
unsigned int tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
unsigned int datalen, reqlen, nexthdr_off;
int oldsstate, oldcstate; int oldsstate, oldcstate;
int ret; int ret;
u_int16_t msg;
/* don't do any tracking before tcp handshake complete */ /* don't do any tracking before tcp handshake complete */
if (ctinfo != IP_CT_ESTABLISHED if (ctinfo != IP_CT_ESTABLISHED
...@@ -648,6 +606,23 @@ conntrack_pptp_help(struct sk_buff **pskb, ...@@ -648,6 +606,23 @@ conntrack_pptp_help(struct sk_buff **pskb,
return NF_ACCEPT; return NF_ACCEPT;
} }
ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
if (!ctlh)
return NF_ACCEPT;
nexthdr_off += sizeof(_ctlh);
datalen -= sizeof(_ctlh);
reqlen = datalen;
msg = ntohs(ctlh->messageType);
if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
return NF_ACCEPT;
if (reqlen > sizeof(*pptpReq))
reqlen = sizeof(*pptpReq);
pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
if (!pptpReq)
return NF_ACCEPT;
oldsstate = info->sstate; oldsstate = info->sstate;
oldcstate = info->cstate; oldcstate = info->cstate;
...@@ -657,11 +632,11 @@ conntrack_pptp_help(struct sk_buff **pskb, ...@@ -657,11 +632,11 @@ conntrack_pptp_help(struct sk_buff **pskb,
* established from PNS->PAC. However, RFC makes no guarantee */ * established from PNS->PAC. However, RFC makes no guarantee */
if (dir == IP_CT_DIR_ORIGINAL) if (dir == IP_CT_DIR_ORIGINAL)
/* client -> server (PNS -> PAC) */ /* client -> server (PNS -> PAC) */
ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
ctinfo); ctinfo);
else else
/* server -> client (PAC -> PNS) */ /* server -> client (PAC -> PNS) */
ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
ctinfo); ctinfo);
DEBUGP("sstate: %d->%d, cstate: %d->%d\n", DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
oldsstate, info->sstate, oldcstate, info->cstate); oldsstate, info->sstate, oldcstate, info->cstate);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment