[NETFILTER]: PPTP conntrack: consolidate header parsing
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
a1073406a1
commit
4c651756d5
@@ -291,60 +291,21 @@ out_unexpect_orig:
|
|||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
* 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);
|
||||||
|
Reference in New Issue
Block a user