diff options
author | Patrick McHardy <kaber@trash.net> | 2006-09-20 15:10:06 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:20:15 -0400 |
commit | 4c651756d502e72a68b0bc6fb20bb18c68785227 (patch) | |
tree | 049a27ab3d5e8e48d9d86bffbb5125e90e903a17 /net/ipv4 | |
parent | a1073406a124c1d3b33a0f06bfb8078a9ddd1985 (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.c | 119 |
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 | ||
294 | static 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 | |||
310 | static inline int | 294 | static inline int |
311 | pptp_inbound_pkt(struct sk_buff **pskb, | 295 | pptp_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 | ||
481 | static inline int | 442 | static inline int |
482 | pptp_outbound_pkt(struct sk_buff **pskb, | 443 | pptp_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 | ||
538 | static 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 */ |
598 | static int | 555 | static 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); |