23 #include <linux/module.h>
26 #include <linux/tcp.h>
35 #define NF_CT_PPTP_VERSION "3.1"
48 unsigned int protoff,
struct PptpControlHeader *ctlh,
55 unsigned int protoff,
struct PptpControlHeader *ctlh,
70 #if defined(DEBUG) || defined(CONFIG_DYNAMIC_DEBUG)
74 "START_SESSION_REQUEST",
75 "START_SESSION_REPLY",
76 "STOP_SESSION_REQUEST",
86 "CALL_DISCONNECT_NOTIFY",
94 #define MINS * 60 SECS
95 #define HOURS * 60 MINS
97 #define PPTP_GRE_TIMEOUT (10 MINS)
98 #define PPTP_GRE_STREAM_TIMEOUT (5 HOURS)
100 static void pptp_expectfn(
struct nf_conn *ct,
103 struct net *
net = nf_ct_net(ct);
117 nf_nat_pptp_expectfn(ct, exp);
124 pr_debug(
"trying to unexpect other dir: ");
125 nf_ct_dump_tuple(&inv_t);
140 static int destroy_sibling_or_exp(
struct net *
net,
struct nf_conn *ct,
148 pr_debug(
"trying to timeout ct or exp for tuple ");
153 sibling = nf_ct_tuplehash_to_ctrack(h);
154 pr_debug(
"setting timeout of conntrack %p to 0\n", sibling);
156 sibling->
proto.
gre.stream_timeout = 0;
158 sibling->
timeout.function((
unsigned long)sibling);
164 pr_debug(
"unexpect_related of expect %p\n", exp);
174 static void pptp_destroy_siblings(
struct nf_conn *ct)
176 struct net *net = nf_ct_net(ct);
187 if (!destroy_sibling_or_exp(net, ct, &t))
188 pr_debug(
"failed to timeout original pns->pac ct/exp\n");
195 if (!destroy_sibling_or_exp(net, ct, &t))
196 pr_debug(
"failed to timeout reply pac->pns ct/exp\n");
230 IPPROTO_GRE, &callid, &peer_callid);
231 exp_reply->
expectfn = pptp_expectfn;
235 nf_nat_pptp_exp_gre(exp_orig, exp_reply);
236 if (nf_ct_expect_related(exp_orig) != 0)
238 if (nf_ct_expect_related(exp_reply) != 0)
239 goto out_unexpect_orig;
243 goto out_unexpect_both;
246 goto out_unexpect_both;
265 pptp_inbound_pkt(
struct sk_buff *skb,
unsigned int protoff,
266 struct PptpControlHeader *ctlh,
267 union pptp_ctrl_union *pptpReq,
277 msg =
ntohs(ctlh->messageType);
281 case PPTP_START_SESSION_REPLY:
285 if (pptpReq->srep.resultCode == PPTP_START_OK)
291 case PPTP_STOP_SESSION_REPLY:
295 if (pptpReq->strep.resultCode == PPTP_STOP_OK)
301 case PPTP_OUT_CALL_REPLY:
309 cid = pptpReq->ocack.callID;
310 pcid = pptpReq->ocack.peersCallID;
313 pr_debug(
"%s, CID=%X, PCID=%X\n", pptp_msg_name[msg],
316 if (pptpReq->ocack.resultCode == PPTP_OUTCALL_CONNECT) {
319 exp_gre(ct, cid, pcid);
324 case PPTP_IN_CALL_REQUEST:
329 cid = pptpReq->icreq.callID;
335 case PPTP_IN_CALL_CONNECT:
343 pcid = pptpReq->iccon.peersCallID;
353 exp_gre(ct, cid, pcid);
356 case PPTP_CALL_DISCONNECT_NOTIFY:
358 cid = pptpReq->disc.callID;
363 pptp_destroy_siblings(ct);
366 case PPTP_WAN_ERROR_NOTIFY:
367 case PPTP_SET_LINK_INFO:
368 case PPTP_ECHO_REQUEST:
369 case PPTP_ECHO_REPLY:
379 return nf_nat_pptp_inbound(skb, ct, ctinfo,
380 protoff, ctlh, pptpReq);
384 pr_debug(
"invalid %s: type=%d cid=%u pcid=%u "
385 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
386 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
393 pptp_outbound_pkt(
struct sk_buff *skb,
unsigned int protoff,
394 struct PptpControlHeader *ctlh,
395 union pptp_ctrl_union *pptpReq,
405 msg =
ntohs(ctlh->messageType);
409 case PPTP_START_SESSION_REQUEST:
416 case PPTP_STOP_SESSION_REQUEST:
421 case PPTP_OUT_CALL_REQUEST:
427 cid = pptpReq->ocreq.callID;
432 case PPTP_IN_CALL_REPLY:
438 cid = pptpReq->icack.callID;
439 pcid = pptpReq->icack.peersCallID;
442 pr_debug(
"%s, CID=%X PCID=%X\n", pptp_msg_name[msg],
445 if (pptpReq->icack.resultCode == PPTP_INCALL_ACCEPT) {
453 case PPTP_CALL_CLEAR_REQUEST:
463 case PPTP_SET_LINK_INFO:
464 case PPTP_ECHO_REQUEST:
465 case PPTP_ECHO_REPLY:
475 return nf_nat_pptp_outbound(skb, ct, ctinfo,
476 protoff, ctlh, pptpReq);
480 pr_debug(
"invalid %s: type=%d cid=%u pcid=%u "
481 "cstate=%d sstate=%d pns_cid=%u pac_cid=%u\n",
482 msg <= PPTP_MSG_MAX ? pptp_msg_name[msg] : pptp_msg_name[0],
488 static const unsigned int pptp_msg_size[] = {
489 [PPTP_START_SESSION_REQUEST] =
sizeof(
struct PptpStartSessionRequest),
490 [PPTP_START_SESSION_REPLY] =
sizeof(
struct PptpStartSessionReply),
491 [PPTP_STOP_SESSION_REQUEST] =
sizeof(
struct PptpStopSessionRequest),
492 [PPTP_STOP_SESSION_REPLY] =
sizeof(
struct PptpStopSessionReply),
493 [PPTP_OUT_CALL_REQUEST] =
sizeof(
struct PptpOutCallRequest),
494 [PPTP_OUT_CALL_REPLY] =
sizeof(
struct PptpOutCallReply),
495 [PPTP_IN_CALL_REQUEST] =
sizeof(
struct PptpInCallRequest),
496 [PPTP_IN_CALL_REPLY] =
sizeof(
struct PptpInCallReply),
497 [PPTP_IN_CALL_CONNECT] =
sizeof(
struct PptpInCallConnected),
498 [PPTP_CALL_CLEAR_REQUEST] =
sizeof(
struct PptpClearCallRequest),
499 [PPTP_CALL_DISCONNECT_NOTIFY] =
sizeof(
struct PptpCallDisconnectNotify),
500 [PPTP_WAN_ERROR_NOTIFY] =
sizeof(
struct PptpWanErrorNotify),
501 [PPTP_SET_LINK_INFO] =
sizeof(
struct PptpSetLinkInfo),
506 conntrack_pptp_help(
struct sk_buff *skb,
unsigned int protoff,
512 const struct tcphdr *tcph;
514 const struct pptp_pkt_hdr *pptph;
515 struct pptp_pkt_hdr _pptph;
516 struct PptpControlHeader _ctlh, *ctlh;
517 union pptp_ctrl_union _pptpReq, *pptpReq;
518 unsigned int tcplen = skb->
len - protoff;
519 unsigned int datalen, reqlen, nexthdr_off;
520 int oldsstate, oldcstate;
528 nexthdr_off = protoff;
529 tcph = skb_header_pointer(skb, nexthdr_off,
sizeof(_tcph), &_tcph);
531 nexthdr_off += tcph->doff * 4;
532 datalen = tcplen - tcph->doff * 4;
534 pptph = skb_header_pointer(skb, nexthdr_off,
sizeof(_pptph), &_pptph);
536 pr_debug(
"no full PPTP header, can't track\n");
539 nexthdr_off +=
sizeof(_pptph);
540 datalen -=
sizeof(_pptph);
543 if (
ntohs(pptph->packetType) != PPTP_PACKET_CONTROL ||
544 ntohl(pptph->magicCookie) != PPTP_MAGIC_COOKIE) {
549 ctlh = skb_header_pointer(skb, nexthdr_off,
sizeof(_ctlh), &_ctlh);
552 nexthdr_off +=
sizeof(_ctlh);
553 datalen -=
sizeof(_ctlh);
556 msg =
ntohs(ctlh->messageType);
557 if (msg > 0 && msg <= PPTP_MSG_MAX && reqlen < pptp_msg_size[msg])
559 if (reqlen >
sizeof(*pptpReq))
560 reqlen =
sizeof(*pptpReq);
562 pptpReq = skb_header_pointer(skb, nexthdr_off, reqlen, &_pptpReq);
569 spin_lock_bh(&nf_pptp_lock);
575 ret = pptp_outbound_pkt(skb, protoff, ctlh, pptpReq, reqlen, ct,
579 ret = pptp_inbound_pkt(skb, protoff, ctlh, pptpReq, reqlen, ct,
581 pr_debug(
"sstate: %d->%d, cstate: %d->%d\n",
583 spin_unlock_bh(&nf_pptp_lock);
599 .tuple.src.u.tcp.port =
cpu_to_be16(PPTP_CONTROL_PORT),
601 .help = conntrack_pptp_help,
602 .destroy = pptp_destroy_siblings,
603 .expect_policy = &pptp_exp_policy,
606 static void nf_conntrack_pptp_net_exit(
struct net *net)
612 .exit = nf_conntrack_pptp_net_exit,
615 static int __init nf_conntrack_pptp_init(
void)
628 static void __exit nf_conntrack_pptp_fini(
void)