aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2006-09-20 15:10:06 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:20:15 -0400
commit4c651756d502e72a68b0bc6fb20bb18c68785227 (patch)
tree049a27ab3d5e8e48d9d86bffbb5125e90e903a17 /net/ipv4
parenta1073406a124c1d3b33a0f06bfb8078a9ddd1985 (diff)
[NETFILTER]: PPTP conntrack: consolidate header parsing
Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r--net/ipv4/netfilter/ip_conntrack_helper_pptp.c119
1 files changed, 47 insertions, 72 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
index 3b5464fa4217..9a98a6ce1901 100644
--- a/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
+++ b/net/ipv4/netfilter/ip_conntrack_helper_pptp.c
@@ -291,60 +291,21 @@ out_unexpect_orig:
291 goto out_put_both; 291 goto out_put_both;
292} 292}
293 293
294static const unsigned int pptp_msg_size[] = {
295 [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest),
296 [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply),
297 [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest),
298 [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply),
299 [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest),
300 [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply),
301 [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest),
302 [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply),
303 [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected),
304 [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest),
305 [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify),
306 [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify),
307 [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo),
308};
309
310static inline int 294static inline int
311pptp_inbound_pkt(struct sk_buff **pskb, 295pptp_inbound_pkt(struct sk_buff **pskb,
312 struct tcphdr *tcph, 296 struct PptpControlHeader *ctlh,
313 unsigned int nexthdr_off, 297 union pptp_ctrl_union *pptpReq,
314 unsigned int datalen, 298 unsigned int reqlen,
315 struct ip_conntrack *ct, 299 struct ip_conntrack *ct,
316 enum ip_conntrack_info ctinfo) 300 enum ip_conntrack_info ctinfo)
317{ 301{
318 struct PptpControlHeader _ctlh, *ctlh;
319 unsigned int reqlen;
320 union pptp_ctrl_union _pptpReq, *pptpReq;
321 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; 302 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
322 u_int16_t msg; 303 u_int16_t msg;
323 __be16 cid, pcid; 304 __be16 cid, pcid;
324 305
325 ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
326 if (!ctlh) {
327 DEBUGP("error during skb_header_pointer\n");
328 return NF_ACCEPT;
329 }
330 nexthdr_off += sizeof(_ctlh);
331 datalen -= sizeof(_ctlh);
332
333 reqlen = datalen;
334 if (reqlen > sizeof(*pptpReq))
335 reqlen = sizeof(*pptpReq);
336 pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
337 if (!pptpReq) {
338 DEBUGP("error during skb_header_pointer\n");
339 return NF_ACCEPT;
340 }
341
342 msg = ntohs(ctlh->messageType); 306 msg = ntohs(ctlh->messageType);
343 DEBUGP("inbound control message %s\n", pptp_msg_name[msg]); 307 DEBUGP("inbound control message %s\n", pptp_msg_name[msg]);
344 308
345 if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
346 return NF_ACCEPT;
347
348 switch (msg) { 309 switch (msg) {
349 case PPTP_START_SESSION_REPLY: 310 case PPTP_START_SESSION_REPLY:
350 /* server confirms new control session */ 311 /* server confirms new control session */
@@ -480,38 +441,19 @@ pptp_inbound_pkt(struct sk_buff **pskb,
480 441
481static inline int 442static inline int
482pptp_outbound_pkt(struct sk_buff **pskb, 443pptp_outbound_pkt(struct sk_buff **pskb,
483 struct tcphdr *tcph, 444 struct PptpControlHeader *ctlh,
484 unsigned int nexthdr_off, 445 union pptp_ctrl_union *pptpReq,
485 unsigned int datalen, 446 unsigned int reqlen,
486 struct ip_conntrack *ct, 447 struct ip_conntrack *ct,
487 enum ip_conntrack_info ctinfo) 448 enum ip_conntrack_info ctinfo)
488{ 449{
489 struct PptpControlHeader _ctlh, *ctlh;
490 unsigned int reqlen;
491 union pptp_ctrl_union _pptpReq, *pptpReq;
492 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; 450 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
493 u_int16_t msg; 451 u_int16_t msg;
494 __be16 cid, pcid; 452 __be16 cid, pcid;
495 453
496 ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
497 if (!ctlh)
498 return NF_ACCEPT;
499 nexthdr_off += sizeof(_ctlh);
500 datalen -= sizeof(_ctlh);
501
502 reqlen = datalen;
503 if (reqlen > sizeof(*pptpReq))
504 reqlen = sizeof(*pptpReq);
505 pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
506 if (!pptpReq)
507 return NF_ACCEPT;
508
509 msg = ntohs(ctlh->messageType); 454 msg = ntohs(ctlh->messageType);
510 DEBUGP("outbound control message %s\n", pptp_msg_name[msg]); 455 DEBUGP("outbound control message %s\n", pptp_msg_name[msg]);
511 456
512 if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
513 return NF_ACCEPT;
514
515 switch (msg) { 457 switch (msg) {
516 case PPTP_START_SESSION_REQUEST: 458 case PPTP_START_SESSION_REQUEST:
517 /* client requests for new control session */ 459 /* client requests for new control session */
@@ -593,6 +535,21 @@ pptp_outbound_pkt(struct sk_buff **pskb,
593 return NF_ACCEPT; 535 return NF_ACCEPT;
594} 536}
595 537
538static const unsigned int pptp_msg_size[] = {
539 [PPTP_START_SESSION_REQUEST] = sizeof(struct PptpStartSessionRequest),
540 [PPTP_START_SESSION_REPLY] = sizeof(struct PptpStartSessionReply),
541 [PPTP_STOP_SESSION_REQUEST] = sizeof(struct PptpStopSessionRequest),
542 [PPTP_STOP_SESSION_REPLY] = sizeof(struct PptpStopSessionReply),
543 [PPTP_OUT_CALL_REQUEST] = sizeof(struct PptpOutCallRequest),
544 [PPTP_OUT_CALL_REPLY] = sizeof(struct PptpOutCallReply),
545 [PPTP_IN_CALL_REQUEST] = sizeof(struct PptpInCallRequest),
546 [PPTP_IN_CALL_REPLY] = sizeof(struct PptpInCallReply),
547 [PPTP_IN_CALL_CONNECT] = sizeof(struct PptpInCallConnected),
548 [PPTP_CALL_CLEAR_REQUEST] = sizeof(struct PptpClearCallRequest),
549 [PPTP_CALL_DISCONNECT_NOTIFY] = sizeof(struct PptpCallDisconnectNotify),
550 [PPTP_WAN_ERROR_NOTIFY] = sizeof(struct PptpWanErrorNotify),
551 [PPTP_SET_LINK_INFO] = sizeof(struct PptpSetLinkInfo),
552};
596 553
597/* track caller id inside control connection, call expect_related */ 554/* track caller id inside control connection, call expect_related */
598static int 555static int
@@ -600,16 +557,17 @@ conntrack_pptp_help(struct sk_buff **pskb,
600 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo) 557 struct ip_conntrack *ct, enum ip_conntrack_info ctinfo)
601 558
602{ 559{
603 struct pptp_pkt_hdr _pptph, *pptph;
604 struct tcphdr _tcph, *tcph;
605 u_int32_t tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
606 u_int32_t datalen;
607 int dir = CTINFO2DIR(ctinfo); 560 int dir = CTINFO2DIR(ctinfo);
608 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info; 561 struct ip_ct_pptp_master *info = &ct->help.ct_pptp_info;
609 unsigned int nexthdr_off; 562 struct tcphdr _tcph, *tcph;
610 563 struct pptp_pkt_hdr _pptph, *pptph;
564 struct PptpControlHeader _ctlh, *ctlh;
565 union pptp_ctrl_union _pptpReq, *pptpReq;
566 unsigned int tcplen = (*pskb)->len - (*pskb)->nh.iph->ihl * 4;
567 unsigned int datalen, reqlen, nexthdr_off;
611 int oldsstate, oldcstate; 568 int oldsstate, oldcstate;
612 int ret; 569 int ret;
570 u_int16_t msg;
613 571
614 /* don't do any tracking before tcp handshake complete */ 572 /* don't do any tracking before tcp handshake complete */
615 if (ctinfo != IP_CT_ESTABLISHED 573 if (ctinfo != IP_CT_ESTABLISHED
@@ -648,6 +606,23 @@ conntrack_pptp_help(struct sk_buff **pskb,
648 return NF_ACCEPT; 606 return NF_ACCEPT;
649 } 607 }
650 608
609 ctlh = skb_header_pointer(*pskb, nexthdr_off, sizeof(_ctlh), &_ctlh);
610 if (!ctlh)
611 return NF_ACCEPT;
612 nexthdr_off += sizeof(_ctlh);
613 datalen -= sizeof(_ctlh);
614
615 reqlen = datalen;
616 msg = ntohs(ctlh->messageType);
617 if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
618 return NF_ACCEPT;
619 if (reqlen > sizeof(*pptpReq))
620 reqlen = sizeof(*pptpReq);
621
622 pptpReq = skb_header_pointer(*pskb, nexthdr_off, reqlen, &_pptpReq);
623 if (!pptpReq)
624 return NF_ACCEPT;
625
651 oldsstate = info->sstate; 626 oldsstate = info->sstate;
652 oldcstate = info->cstate; 627 oldcstate = info->cstate;
653 628
@@ -657,11 +632,11 @@ conntrack_pptp_help(struct sk_buff **pskb,
657 * established from PNS->PAC. However, RFC makes no guarantee */ 632 * established from PNS->PAC. However, RFC makes no guarantee */
658 if (dir == IP_CT_DIR_ORIGINAL) 633 if (dir == IP_CT_DIR_ORIGINAL)
659 /* client -> server (PNS -> PAC) */ 634 /* client -> server (PNS -> PAC) */
660 ret = pptp_outbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, 635 ret = pptp_outbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
661 ctinfo); 636 ctinfo);
662 else 637 else
663 /* server -> client (PAC -> PNS) */ 638 /* server -> client (PAC -> PNS) */
664 ret = pptp_inbound_pkt(pskb, tcph, nexthdr_off, datalen, ct, 639 ret = pptp_inbound_pkt(pskb, ctlh, pptpReq, reqlen, ct,
665 ctinfo); 640 ctinfo);
666 DEBUGP("sstate: %d->%d, cstate: %d->%d\n", 641 DEBUGP("sstate: %d->%d, cstate: %d->%d\n",
667 oldsstate, info->sstate, oldcstate, info->cstate); 642 oldsstate, info->sstate, oldcstate, info->cstate);